개발/React

무한 props 없애기 Redux

pizzaYami 2023. 8. 23.

Redux가 뭔데 왜 쓰는데

 

Redux는 props 없이 state를 공유할 수 있게 도와주는 라이브러리이다.

store.js에 state들을 보관하고 다른 컴포넌트에 쏴줄수있다.

사이트가 커지면 유용하게 써먹을 수 있다.

 

Redux 설치 및 셋팅

Redux 설치

 

아래의 코드를 터미널에 입력하면된다.

npm install @reduxjs/toolkit react-redux

redux toolkit이라는 라이브러리를 사용할 건데 redux의 문법을 쉽게 만드는 라이브러리이다.

 

설치하기전에 

"react"

"react-dom"

의 버전이 18.1.x 이상인지 확인하자.

 

확인법은 package.json에서 확인가능하다.

 

 

Redux 셋팅

 

아무곳에 store.js 파일을 만들고 아래 코드에 복붙해준다.

여기가 바로 state를 보관하는 파일이다.

import { configureStore } from '@reduxjs/toolkit'

export default configureStore({
  reducer: { }
})

 

index.js파일에 들어가서 

Provider와 store를 import해온다.

밑에 <Provider store={import해온거}> 이걸로 <App/> 을 감싸면 된다.

이러면 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>
);

 

store에 보관하는 법

 

createSlice(), configureStore()  import해오기

1. createSlice()로 state만들기

{ name : 'state이름', initialState : 'state값' } 

2. configureStore()안에 등록

{ 작명 : createSlice만든거변수명.reducer }

(store.js)
import { configureStore, createSlice } from '@reduxjs/toolkit'

let user = createSlice({
  name : 'user',
  initialState : 'kim'
})

export default configureStore({
  reducer: {
    user : user.reducer
  }
})

 

store에 있는거 가져다 쓰는법

useSelector import해오기

let a = useSelector((state) => state.user ) 로 가져와서 쓰면된다.

(Cart.js)

import { useSelector } from "react-redux"

function Cart(){
  let a = useSelector((state) => state.user ) 
  console.log(a)

  return (생략)
}

 

store에 있는 state 변경하는법

 

store에 state변경함수를 만들어서

컴포넌트에서 state변경함수를 통해서 state변경시키면된다.

뭔소리인지 모르겠으면 밑에 설명을 보자.

 

store.js에 state변경함수 만들기

1. reducers : { } 안에 함수를 만들어준다.

2. 함수명은 자기 맴

3. 파라미터는 기존의 state가 된다. (여기서 "kim")

4. return 우측 새로운 state입력하면 state 바꿔준다. ("kim" => "john kim")

5. export해준다.

let user = createSlice({
  name : 'user',
  initialState : 'kim',
  reducers : {
    changeName(state){
      return 'john ' + state
    }
  }
})

export let { changeName } = user.actions

 

state변경함수 import해서 사용하기

store.js에서 원하는 state변경함수 가져온다.

useDispatch 라는 것도 라이브러리에서 가져온다.

그리고 dispatch( state변경함수() ) 이렇게 감싸서 실행하면 state 진짜로 변경된다. 

Cart.js)

import { useDispatch, useSelector } from "react-redux"
import { changeName } from "./../store.js"

(생략) 

<button onClick={()=>{
  dispatch(changeName())
}}>버튼임</button>

 

state가 object/array일 경우 변경하는 법

 

redux state가 {name : 'kim', age : 20}처럼 생긴 자료를 name: "park"으로 변경하고싶다면 어떻게 해야할까?

 

밑의 코드처럼 state전체를 바꾸는 방법이 있다.

let user = createSlice({
  name : 'user',
  initialState : {name : 'kim', age : 20},
  reducers : {
    changeName(state){
      return {name : 'park', age : 20}
    }
  }
})

 

하지만 전체코드를 바꾸는것보다는 하나를 불러와서 바꿔주는게 낫다.

let user = createSlice({
  name : 'user',
  initialState : {name : 'kim', age : 20},
  reducers : {
    changeName(state){
      state.name = 'park'
    }
  }
})

 

state변경함수에 파라미터를 넣고싶다면 파라미터문법 사용

 

changeName의 두 번째 파라미터에 action을 넣고 action.payload를 넣어보자.

export해주고

(store.js)
let user = createSlice({
  name : 'user',
  initialState : {name : 'kim', age : 20},
  reducers : {
    changeName(state, action){
      state.name = action.payload
    }
  }
})

export let { changeName } = user.actions;

Cart.js에서 import해오고

changeName("바꾸고 싶은 이름")으로 코드를 짜면

user.name이 "바꾸고 싶은 이름"에 넣은 글자로 변경되는것을 확인할 수 있다.

(Cart.js)

import { changeName } from "./../store.js";

<button
    onClick={(a, i) => {
    	dispatch(changeName("cho"));
    }}
    >
    	버튼임
</button>

 

문제풀기

 

이거해봐야 좀 이해가 된다.

 

1. 수량 + 1 기능만들기

state에 있는  count를 버튼을 누르면 +1 되게하는 기능을 만들어보자.

let cart = createSlice({
  name : 'cart',
  initialState : [
    {id : 0, name : 'White and Black', count : 2},
    {id : 2, name : 'Grey Yordan', count : 1}
  ]
})

 

findIndex()나 find()를 사용해서 a.id === action.payload가 같은 객체만 가져오도록했다.

여기서 a는 state에 저장된 객체하나하나를 말하고

action.payload는 나중에 보낸 state변경함수에 파라미터로 들어가는 값이다.

(store.js)

let cart = createSlice({
  name : 'cart',
  initialState : [
    {id : 0, name : 'White and Black', count : 2},
    {id : 2, name : 'Grey Yordan', count : 1}
  ],
  reducers : {
    addCount(state, action){
      let 번호 = state.findIndex((a)=>{ return a.id === action.payload })
      state[번호].count++
    }
  }
})


(Cart.js)

dispatch(addCount(state.cart[i].id))

 

2. 주문버튼누르면 state에 새로운 상품추가

state변경함수를 여러개 사용해서 추가해보자.

기존의 state에 push를 이용해서 추가하는 방식이다.

export도 추가해주자.

(store.js)
let cart = createSlice({
  name : 'cart',
  initialState : [
    {id : 0, name : 'White and Black', count : 2},
    {id : 2, name : 'Grey Yordan', count : 1}
  ],
  reducers : {
    addCount(state, action){
      state[action.payload].count++
    },
    addItem(state, action){
      state.push(action.payload)
    }
  }
})

export let { increace, addItem } = cart.actions;

cart.js에서 import해오고

addItem()함수에 파라미터로 넣고싶은 상품 정보를 넣어주자.

(Cart.js)

import { increace, changeName, addItem } from "./../store.js";

<button
    onClick={() => {
    	dispatch(
    	addItem({ id: { i }, name: "Red knit", count: 1 })
   	 );
    }}
>
물품추가
</button>

댓글