React x Redux

5tr1ker·2022년 4월 7일
post-thumbnail

Redux 함수

Store 스토어

한 어플리케이션마다 하나의 스토어를 가지게 됩니다. 스토어에는 앱상태와 reducer 가 내장되어있습니다.

Subscribe 구독

subscribe 함수에 값을 전달하면 , 액션이 dispatch 되었을 때 전달한 함수 값이 실행됩니다.

dispatch 디스패치

store 내장함수중 하나로써 action을 실행시키는 함수입니다. dispatcher를 실행하면 해당 액션의 로직을 실행합니다.

Reducer 리듀서

state, action 를 받아서 새로운 state 를 반환하는 함수입니다. 말 그대로 어떤 상태 변화에 따라 state로 값을 변경한 후 새로운 state로 변경합니다.

Action 액션

어떤 상태 변화를 일으킬것인지 결정하는 함수입니다. subscribe 되어있는 함수에 값을 update 시킵니다.

Action 함수

Action을 만드는 함수입니다. 파라미터를 받아와서 Action 을 생성합니다. 이 함수는 export 해서 다른 컴포넌트에서 이용할 수 있게 합니다.

Redux 흐름

  1. subscribe (상태 변경 감지되면 알림을 받음)
  2. action (상태 변화)
  3. dispatch (상태 업데이트)
  4. store (업데이트된 값 수정)
  5. 변화된 값들을 수정

Redux 규칙 ( 3원칙 )

1. Store는 한개만

한 어플리케이션에는 store는 단 1개만 존재해야한다.

2. 읽기 전용 상태

state를 직접 변경해서는 안됩니다. state를 변경하는 방법은 Action으로 Reducer 에 dispatch해서 값을 변경하는 방법을 이용해야합니다. state는 오직 Reducer만 변경합니다.

3. Reducer는 순수 함수여야 한다.

Reducer 함수는 parameter로 기존의 state와 Action을 받는데, 이전 상태는 절대로 건드리지 않고 변화를 일으킨 새로운 상태 객체를 만들어서 반환합니다.
또한 똑같은 파라미터로 호출된 리듀서는 함상 같은 값을 반환해야합니다.

Redux 구현

본 글은 해당 게시글 코드에서 변형했습니다.
https://react.vlpt.us/redux/04-make-modules.html

모듈 구현하기

myreduce_module.js 파일
주석문을 잘 봐주세요.

액션과 액션함수 , 리듀서를 구현합니다.

// Action 변수 만듭니다.
// Action의 이름에 접두사를 넣어서 다른 모듈과 중복되는것을 방지할 수 있습니다.
const DATA_INCREASE = 'count/INCREASE';
const DATA_DECREASE = 'count/DECREASE';
const DATA_SETTING = 'count/SETTING';

// 액션 함수
// 해당 함수가 실행되었을 때 액션이 실행될 수 있게 해줍니다.
export const increase = () => ({type: DATA_INCREASE});
export const decrease = () => ({type: DATA_DECREASE});
export const data_setting = (set) => ({type: DATA_SETTING , set});
// 인자도 같이 되었을때 하단 reducer 에서 action.set 으로 값을 이용할 수 있게 같이 보내줍니다.

//초기 값
const initdata = ({
  number: 1,
  setting: 1
});


//Reducer
// 함수명은 임의로 설정해도 됩니다.
// Reducer에게 state 값을 설정시켜 줍니다. 그러면 dispatch로 Action이 실행되면 해당 Reducer가 실행됩니다.
export default function reducer(state = initdata , action) {
  switch(action.type) {
      case DATA_SETTING:
          return {
              ...state ,  // 값 불변성 보장하기 위해 state 이전값을 같이 보내줍니다.
              setting: action.set
          }
      case DATA_INCREASE:
          return {
              ...state ,
              number : state.number + state.setting
          }
      case DATA_DECREASE:
          return {
              ...state ,
              number : state.number - state.setting
          }
      default:
          return state;
  }
}

Redux 코드 구현

해당 코드는 값을 update하는 dispatch , store에서 값을 가져오는 useSelector() 를 구현합니다.

import { useDispatch, useSelector } from "react-redux";
import { data_setting, decrease, increase } from "./myreduce_module";
import MyProps from "./props";


const Myreduce = () => {
    // useSelector는 reducer의 store안에 값을 가져오는데 사용합니다.
    const {number , setting} = useSelector(state => ({
        number: state.reducer.number , // 중간에 변수명은 최상위 store 에서 reducer 인자로 전달한 이름을 그대로 넣어줍니다. ( App.js 참조)
        setting: state.reducer.setting // module 에서 설정한 변수명과 동일해야합니다.
    }));

  // 상태값을 update 하기위해 dispatch 함수를 가져옵니다.
  const dispatch = useDispatch(); 

  // dispatch 인자에 module에서 실행할 export 한 액션 함수명을 넣습니다.
  const onIncrease = () => dispatch(increase()); 
  const onDecrease = () => dispatch(decrease());
  const onSets = set => dispatch(data_setting(set));
    return(<MyProps
        number={number}
        diff={setting}
        onIncrease={onIncrease}
        onDecrease={onDecrease}
        setting={onSets}
      />)
}

export default Myreduce;

Props 코드


function MyProps({ number, diff, onIncrease, onDecrease, setting }) {
  const onChange = e => {
    setting(parseInt(e.target.value, 10));
  };
  return (
    <div>
      <h1>{number}</h1>
      <div>
        <input type="number" onChange={onChange} />
        <button onClick={onIncrease}>+</button>
        <button onClick={onDecrease}>-</button>
      </div>
    </div>
  );
}

export default MyProps;

App.js 코드

import { combineReducers, createStore } from 'redux';
import reducer from './reduces/myreduce_module';
import Myreduce from './reduces/myreduce';

function App() {
  const reducers = combineReducers({reducer}); // 리듀서 묶음
  const store = createStore(reducers); // store 생성
  return (
    <Provider store={store}>
    	<Myreduce/>
    </Provider>
  );
}

GitHub

https://github.com/5tr1ker/react-redux

profile
https://github.com/5tr1ker

0개의 댓글