이번 포스팅에서는 react-redux 라이브러리에서 제공하는 Provider를 사용하여 app 전체에서 store를 사용할 수 있는 방법과 useSelector를 사용하여 상태값을 가져오는 방법, useDispatch를 사용하여 상태값을 업데이트 방법에 관해 정리해보려한다.
목차
- react-redux 설치
- Provider를 사용하여 store 공급하기
- useSelector, useDispatch 사용법
1. react-redux 설치
우선 Provider를 사용하기 위해서 아래의 명령어를 실행하여 react-redux를 설치한다.
npm install react-redux --save
2. Provider를 사용하여 store 공급하기
// index.tsx
import React from 'react';
import ReactDOM from 'react-dom/client';
import './index.css';
import App from './App';
import { createStore } from 'redux';
import rootReducer from './reducers';
import { Provider } from 'react-redux';
const root = ReactDOM.createRoot(document.getElementById('root') as HTMLElement);
// store 생성
const store = createStore(rootReducer);
const render = () =>
root.render(
<React.StrictMode>
<Provider store={store}>
<App />
</Provider>
</React.StrictMode>
);
render();
store.subscribe(render);
Provider를 사용하여 App 전체 컴포넌트 에 store를 제공하는 방법은 간단하다.
reducer를 인자로 store생성을 하고 위와 같이 Provider 컴포넌트로 store를 공급할 컴포넌트를 감싸준다. 이때 props로 store를 내려주면 Provider 하위 컴포넌트는 모두 store에 자유롭게 접근할 수 있다.
(store와 reducer 생성 방법은 아래 링크를 참조)
https://kyuntechblog.tistory.com/41
3. useSelector, useDispatch 사용법
//reducers/index.tsx
interface Action {
type: string;
}
const rootReducer = (state: number = 0, action: Action) => {
switch (action.type) {
case 'INCREMENT':
return state + 1;
case 'DECREMENT':
return state - 1;
default:
return state;
}
};
export default rootReducer;
export type RootState = ReturnType<typeof rootReducer>;
// App.tsx
import React, { useState } from 'react';
import './App.css';
import { useDispatch, useSelector } from 'react-redux';
import { RootState } from './reducers';
function App() {
const dispatch = useDispatch();
const counter = useSelector((state:RootState) => state);
return (
<div className='App'>
<div className='counterApp'>
<button onClick={() => dispatch({ type: 'INCREMENT' })}>+</button>
<span> {counter} </span>
<button onClick={() => dispatch({ type: 'DECREMENT' })}>-</button>
</div>
</div>
);
}
export default App;
위 App은 +, - 버튼으로 숫자를 증감하는 간단한 counter 이다.
useSelector와 useDispatch hook을 사용하기 위해 react-redux에서 useDispatch, useSelector를 import 한다.
useDispatch의 사용법은 위와 같이 useDispatch를 선언하고 상황에 맞는 type 값을 넘겨주면 상태값을 업데이트 할 수있다. 이전 포스팅에서의 store.dispatch의 사용법과 크게 다르지 않다.
useSelector를 보면 state의 타입을 RootState로 지정해주었는데 state 타입을 지정해주지 않으면 에러가 나기에 반드시 위처럼 reducer 에서 type을 리턴해주고 import해서 state의 타입을 항상 지정해주어야 한다.
✔︎ state의 타입을 항상 지정해주지 않으려면 ?
useSelector 훅을 아래처럼 커스텀훅으로 만들어서 사용하면 useSelector 사용시 매번 state 의 타입을 지정해주지 않아도 된다.
//reducers/hooks.tsx
import { TypedUseSelectorHook, useSelector } from 'react-redux';
import type { RootState } from '.';
export const useCustomSelector: TypedUseSelectorHook<RootState> = useSelector;
// App.tsx
import './App.css';
import { useDispatch } from 'react-redux';
import { useCustomSelector } from './reducers/hooks';
function App() {
const dispatch = useDispatch();
const counter = useCustomSelector((state) => state);
return (
<div className='App'>
<div className='counterApp'>
<button onClick={() => dispatch({ type: 'INCREMENT' })}>+</button>
<span> {counter} </span>
<button onClick={() => dispatch({ type: 'DECREMENT' })}>-</button>
</div>
</div>
);
}
export default App;
이렇게 커스텀훅을 만들어주고 위처럼 App.tsx 에서 useCustomSelector를 import 하여 state의 타입을 지정해주지 않고 사용할 수 있다.