[React] 상태관리 라이브러리 Reducx
Redux
Redux는 props 없이 state를 공유할 수 있게 도와주는 라이브러리다.
Redux를 설치하면 JS 파일 하나에 state를 보관할 수 있는데, 이걸 모든 컴포넌트가 직접 꺼내 쓸 수 있다.
그래서 props 문법이 필요없어진다.
설치하기
https://ko.redux.js.org/introduction/getting-started/
Redux 홈페이지에서 설치하면 된다.
설치하기 전 확인사항 1
Redux를 설치하기 전, package.json에서 react와 react-dom의 버전을 확인해야 한다.
이 2가지 버전이 모두 18.1.X 이상이어야 Redux 사용이 가능하다.
1
2
"react": "^18.1.0",
"react-dom": "^18.1.0",
설치하기 전 확인사항 2
Redux toolkit을 설치하도록 하자.
Redux toolkit은 Redux의 개선버전이라고 보면 된다, 문법이 좀 더 쉬워진다.
아래는 홈페이지 내의 설명
여러분이 첫 프로젝트에 Redux를 새로 도입하는 입문자든 기존 앱을 단순화하고 싶은 경험자든 상관 없이, Redux Toolkit은 더 나은 Redux 코드를 만들게 도와줍니다.
1
2
npm install @reduxjs/toolkit
npm install @reduxjs/toolkit react-redux
셋팅하기
1. store.js 파일 생성
state를 보관할 파일을 생성한 후 아래 내용을 복붙한다.
1
2
3
4
5
import { configureStore } from '@reduxjs/toolkit'
export default configureStore({
reducer: { }
})
2. index.js 파일 셋팅
- index.js 파일에 Provider라는 컴포넌트 import와, store.js파일을 import한다.
- 그리고 밑에 <Provider store={import해온것}> 으로
을 감싼다.
이렇게 하면 App과 모든 자식 컴포넌트들은 store.js에 있는 state를 마음껏 꺼내쓸 수 있게된다.
1
2
3
4
5
6
7
8
9
10
11
12
13
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>
);
Redux store에 state 보관하는 법
store.js 에 state를 보관하는 방법
configureStore, createSlice 컴포넌트를 상단에 import한다.
createSlice() 안에 객체를 넣으면 state 하나가 생성된다.
createSlice() == useState() 용도가 비슷하다고 보면 된다.생성한 state를 등록해야 사용가능한데, 등록은 configureStore() 안에 등록한다.
이곳에 등록한 state는 모든 컴포넌트가 자유롭게 사용 가능하다.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
// store.js
import { configureStore, createSlice } from '@reduxjs/toolkit'
let user = createSlice({
name : 'user',
initialState : 'kim'
})
let cart = createSlice({
name : 'cart',
initialState : [
{id : 0, name : 'White and Black', count : 2},
{id : 2, name : 'Grey Yordan', count : 1}
]
})
export default configureStore({
reducer: {
user : user.reducer,
cart : cart.reducer
}
})
Redux store 안에 있는 state 사용하기
아무 컴포넌트에서 useSelector((state)=>{return state}) 를 쓰면 store.js에 있던 모든 state가 그 자리에 남게된다.
1
2
3
4
5
6
7
8
9
10
// Cart.js
import { useSelector } from "react-redux"
function Cart(){
let a = useSelector((state) => { return state } )
console.log(a) // {user: 'kim'}
return (생략)
}
좀더 줄여서 쓸 수도 있음
1
let a = useSelector((state) => state.user )
Redux store 안에 있는 state 변경하기
Redux store를 변경하고 싶으면 아래와 같은 절차로 변경하면 된다.
대략, state를 수정해주는 함수를 store.js 내에 만들고, 이거을 컴포넌트가 필요할때마다 실행하는 식이다.
- store.js에 state 변경해주는 함수 생성
- export
- 필요할 때 import 해서 사용한다. ( 이때에는 dispatch() 로 감싸서 사용 )
1. store.js 안에 state 변경해주는 함수 생성
slice 안에 reducer : { } 열고 이 안에 함수를 만든다.
- 함수 작명 마음대로
- 파라미터 하나 작명하면 그건 기존 state가 된다.
- return 우측에 새로운 state를 입력하면 이걸로 기존 state를 바꿔준다.
1 2 3 4 5 6 7 8 9
let user = createSlice({ name : 'user', initialState : 'kim', reducers : { changeName(state){ return 'john ' + state } } })
2. export 해준다.
아래 코드를 store.js 밑에 추가해준다.
slice이름.actions 라고 적으면 state 변경 함수가 전부 그 자리에 출력된다.
이걸 변수에 저장했다가 export 하라는 뜻
1
export let { changeName } = user.actions
3. 원할때 import 해서 사용한다. 근데 dispatch() 써야함
예를 들어서 Cart.js 컴포넌트에서 버튼을 만들고, 버튼을 누르면 state를 변경하도록 구현 해보자.
- store.js에서 원하는 state 변경 함수를 가져오고
- useDispatch 라이브러리 import
- dispatch ( state변경함수() ) 문법 사용 ````javascript // Cart.js
import { useDispatch, useSelector } from “react-redux” import { changeName } from “./../store.js”
(생략)
<button onClick={()=>{ dispatch(changeName()) }}>버튼임</button>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
## Redux state가 Array, Object 인 경우 변경하기
state를 직접 수정하라고 짜면 된다. 이게 잘 되는 이유는
Immer.js라는 라이브러리가 state 사본을 하나 더 생성해 준 덕분인데, Redux를 설치하면 이 라이브러리가 딸려오기 때문
(참고)
그래서 state 만들 때 문자나 숫자 하나만 필요해도 redux에선 일부러 Array, Objec에 담는 경우가 있다.
(수정이 편리해 지기 때문)
````javascript
// store.js
let user = createSlice({
name : 'user',
initialState : {name : 'kim', age : 20},
reducers : {
changeName(state){
state.name = 'park'
}
}
})
Redux state 변경 시 둘째 파라미터 사용하기
state 변경 함수의 둘째 파라미터를 사용하게 되면
increase(10)
increase(100)
이런 식으로 파라미터를 사용해서 함수 사용이 가능하다.
파라미터에 넣은 자료들은 action.payload 하면 사용할 수 있다.
(참고)
- action.type 하면 state 변경 함수 이름이 나오고
- action.payload 하면 파라미터가 나온다. ````javascript // store.js
let user = createSlice({ name : ‘user’, initialState : {name : ‘kim’, age : 20}, reducers : { increase(state, action){ state.age += action.payload } } })
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
## Redux store 파일 분할하기
Redux store 안에 코드가 길면 파일을 나눠서 사용할 수 있다. import, export 해서 사용할 수 있다.
````javascript
// store.js
import { configureStore, createSlice } from '@reduxjs/toolkit'
import user from './store/userSlice.js' // 파일 import
let cart = createSlice({
name : 'cart',
initialState : [
{id : 0, name : 'White and Black', count : 2},
{id : 2, name : 'Grey Yordan', count : 1}
]
})
export default configureStore({
reducer: {
user : user.reducer,
cart : cart.reducer
}
})
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
// /store/userSlice.js
import { createSlice } from '@reduxjs/toolkit'
let user = createSlice({
name : 'user',
initialState : { name : 'kim', age : 20 },
reducers : {
changeName(state){
state.name = 'park'
},
increase(state, action) {
state.age += action.payload
}
}
})
export let {changeName, increase } = user.actions
export default user
