이번에는 redux-toolkit에 대해 알아보자.
redux는 앞에서도 설명했지만 props 없이 state를 공유할 수 있도록 도와주는 라이브러리다.
npm i @reduxjs/toolkit react-redux
설치방법은 위와 같다.
설치하기 전 package.json에서 react와 react-dom 버전이 18.1.x이상인지 확인한다.
redux-toolkit은 redux의 개선버전이라고 보면 된다.
redux의 복잡성과 보일러플레이트를 줄이기 위한 도구로 효율적이고 쉽게 Redux를 사용할 수 있도록 도와준다.
대부분 새로운 redux 프로젝트에서는 redux-toolkit이 권장되고 있다.
import { configureStore } from '@reduxjs/toolkit';
export default configureStore({
reducer: {}
});
프로젝트의 루트 페이지에 store.js 파일을 만들어 위 코드를 복붙한다.
state들을 보관하는 파일이다.
import { Provider } from 'react-redux';
import store from './store.js';
const root = ReactDOM.createRoot(document.getElementById('root'));
root.render(
<React.StrictMode>
<Provider store={store}>
<BrowserRouter>
<App />
</BrowserRouter>
</Provider>
</React.StrictMode>
);
index.js 파일로 가서 Provider라는 컴포넌트와 아까 작성한 파일을 import 해온다.
그리고 아래 <Provider store={import해온거}>
로 <App/>
를 감싸주면 된다.
그럼`<App>
과 그 모든 자식 컴포넌트는 store.js에 있는 state를 꺼내 쓸 수 있다.
import { configureStore, createSlice } from '@reduxjs/toolkit';
const user = createSlice({
name: 'user',
initialState: 'kim'
});
export default configureStore({
reducer: {
user: user.reducer
}
});
1.createSlice()를 import 해온다음
{ name: 'state이름', initialState: 'state값' } 이렇게 넣으면 state가 생성된다.
createSlice()는 useState()와 비슷하다.
2.state 등록은 configureStore() 안에 하면 된다.
{ 이름: createSlice만든거.reducer } 이렇게 하면 등록 되고, 여기 등록한 state는 모든 컴포넌트가 자유롭게 사용가능하다.
//사용할 컴포넌트
import { useSelector } from 'react-redux';
function 함수명(){
const a = useSelctor((state) => { return state });
console.log(a);;
return (생략)
};
아무 컴포넌트에서 useSelector((state) => { return state })를 사용하게 되면 store에 있는 모든 state가 그 자리에 남는다.
1.store.js 내 state 수정하는 함수 만들기
const user = createSlice({
name: 'user',
initialState: 'kim',
reducers: {
changeName(state){
return 'john' + state
}
}
});
slice 내 reducers: {} 열고 안에 함수를 만들면 된다.
함수 작명은 자유, 파라미터 하나 작명하면 그건 기존 state가 된다, return 우측에 새로운 state작성하면 그걸로 기존 state가 변경된다.
이제 changeName() 사용하면 kim -> john kim으로 변경된다.
2.다른곳에서 사용하기 쉽도록 export하기
export const { changeName } = user.actions
이런 코드를 store.js 아래 작성ㅎ나다.
slice이름.actions라고 적으면 state 변경 함수가 전부 출력된다.
그걸 변수에 저장했다가 export하라는 뜻.
3.원할 때 import하고 dispatch()로 감싸 사용한다.
예시로 컴포넌트에서 버튼을 만들고, 버튼을 누르면 state를 kim -> john kim 이런식으로 변경하고 싶을 때
//원하는 컴포넌트
import { useDispatch, useSelector } from 'react-redux';
import { changeName } from './store.js';
(생략)
<button onClick={()=>{
dispatch(changeName())
}}>버튼</button>
위처럼 작성하면 된다.
store.js에서 원하는 state변경 함수를 가져오고 useDispatch를 import한다.
dispatch(state변경함수()) 이런식으로 감싸 실행하면 state가 변경된다.
{name: 'kim', age: 20} 이렇게 생긴 자료를 state로 만들경우
kim -> park으로 변경하려 한다면
const user = createSlice({
name: 'user',
initialState: {name: 'kim', age: 20},
reducers: {
changeName(state){
return {name: 'park' age: 20}
}
}
});
위처럼 사용하면 changeName() 사용시 변경된다.
const user = createSlice({
name: 'user',
initialState: {name: 'kim', age: 20},
reducers: {
changeName(state){
state.name = 'park'
}
}
});
그러나 위처럼 state를 직접 수정하려고 해도 변경된다.
state를 직접 수정하는 문법을 사용해도 잘되는 이유는 Immer.js 라이브러리가 state 사본을 하나 더 생성해준 덕분인데 Redux 살치할 때 같이 설치되어서 그렇다.
결론은 array/object 자료형은 state를 직접 수정해도 되기 때문에 직접 수정하자.
만약 state에 1씩 더해주는 기능을 만들었는데 10도 더하고 싶고 100도 더하고 싶을 경우 함수에서는 파라미터 문법을 이용하면 되는데, state변경 함수에도 사용 가능하다.
const user = createSlice({
name: 'user',
initialState: {name: 'kim', age: 20},
reducers: {
addAge(state, action){
state.age += action.payload
}
}
});
state변경 함수 둘째 파라미터를 작명하면
addAge(10) addAge(100) 이런식으로 파라미터를 입력해서 사용 가능하다.
파라미터에 넣은 숫자는 a.payload하면 나온다.
action.type하면 state 변경함수 이름이 나오고 action.payload하면 파라미터가 나온다.