Redux는 JS를 사용하는 어느 환경에서도 사용이 가능하다. 따라서 React.js에서도 사용할 수 있는데, 바닐라 JS와 개별 환경이 다르다보니 Redux를 그냥 사용하는 것은 다소 복잡한 일이다. 그래서 React.js에서 더 편하게 Redux를 사용하기 위한 추가적인 라이브러리가 개발되었다.
React.js에서 Redux를 바로 사용하는데 발생하는 불편한 점들을 개선하기 위해 개발된 라이브러리. React.js에서 Redux를 편하게 사용하기 위한 선택적 도구이다.
일반 Redux에서는 reducer 함수를 구현한 다음, createStore 함수를 이용하여 Store를 생성하고 이를 바탕으로 dispatch, getState, render 함수 등을 사용해 주었다.
var store = Redux.createStore(reducer);
var state = store.getState();
store.dispatch({type:'CHANGE_COLOR', color:'red'});
react-redux에서도 Store를 생성할 컴포넌트(index.js나 App.js)에서 마찬가지의 작업을 수행해주어야 한다.
import { createStore } from 'redux';
import { Reducer } from './Redux/Reducer';
const store = createStore(Reducer);
다만 그 다음 과정은 일반 Redux와 다르다. state를 어떤 컴포넌트에게 제공해야하는지, 그 범위를 지정해야한다. react-redux은 이를 위해 Provider 컴포넌트를 제공하고 있다. Provider 컴포넌트는 생성된 store를 인자로 받아야 하며, Provider 아래 존재하는 컴포넌트만 state를 주고받을 수 있다.
<Provider store={store}>
<Component1/>
<Component2/>
</Provider>
react-redux는 state를 가지고 올 때 useSelector 함수를 사용한다.
function Component1() {
function getState(state) {
return state.number;
}
const number = useSelector(getState);
return (
<div>
<h1>{number}</h1>
</div>
);
};
위 컴포넌트에서 getState 함수는 인자로 state를 필요로 한다. 그런데 useSelector 함수를 호출 할때 getState 함수는 아무 인자를 받지 않았음에도 에러가 발생되지 않고 정상적으로 number라는 값을 받아오고 있다.
이는 Store 내부의 Reducer에 존재하는 number의 값이 전역적으로 제공되고 있기 때문이다.
function Component2() {
const dispatch = useDispatch();
return (
<div>
<input type='button' value='R+' onClick={() => { dispatch({ type: '+' }); }} />
</div>
);
};
State를 변경하는 역할은 useDispatch 함수가 수행한다. useDispatch 함수를 호출할 때 인자로는 type, 필요한 경우에 payload를 사용할 수 있다.
type은 Reducer에서 action으로 넘어오는 요청이 어떤 요청인지 구분하는데 사용되며 payload는 Store의 State에 저장할 데이터가 존재할 경우에 사용한다.
store 내부의 state를 어떻게 변경할 것인지를 결정하는 것이 바로 Reducer이며, useDispatch 함수는 Action를 Reducer로 전달하는 역할을 수행한다.
export const Reducer = (currentState, action) => {
const newState = { ...currentState };
if (action.type === '+') {
newState.number++;
};
return newState;
};
Reducer의 동작 과정을 이해하기 위해서는 우선 컴포넌트에서 호출된 useDispatch 함수를 다시 기억해봐야 한다.
dispatch({ type: '+' });
이 호출 구문의 type이 Reducer 함수의 action, action 내부의 type에 해당한다. 이 action.type을 조건으로 사용하는 조건문에 따라 상황에 맞는 코드가 동작하여 Store의 State가 변화하게 되는 것이다.
그런데 위의 코드를 잘 보면 newState라는 변수가 존재하는 것을 알 수 있다. newState는 점 표기법을 이용하여 Store의 기존 State(currentState)를 그대로 가져오는 역할을 하는데, 이는 Redux의 불변성 유지를 위해 새로운 state를 만들기 앞서 기존에 존재하던 state를 복제해야하기 때문이다.