Jaeilit

TIL(7)REDUX_1편 본문

TIL

TIL(7)REDUX_1편

Jaeilit 2021. 9. 24. 21:42
728x90

리덕스는 왜 쓰는가?

 

리액트에서는 단 방향 데이터입니다.

부모 컴포넌트의 데이터를 자식 컴포넌트에게 props 로 넘겨줄 수 있습니다..

하지만 자식이 또 자식을 또 또 자식을 이렇게 트리 구조를 이루게 되면

 

부모이였던 컴포넌트는 조상이되기 됩니다.

 

props를 자식에게 또 그 자식의 자식에게 그 자식의 자식의 자식...

이런식으로 내려가게되기 때문에

 

데이터를 관리하기에는 많이 비효율적입니다.

 

내가 쓰지도 않는데 가지고 있어야할 경우도 생기고,

데이터를 관리하는 점에서도 난잡해질것이며,

거쳐가는 지점이 많다는 것 자체도 비효율입니다.

 

또, 형제끼리는 props를 나누지 못한다는 결정적인 단점도 있습니다. 

 

데이터를 데이터 저장소(컴포넌트 이외의 바깥 장소)에서 관리하며 컴포넌트들이 필요할때마다 빼서 쓰면 어떨까?

부모가 자식에게 자식이 또 그 자식에게 물려주지 않아도 됩니다.

 

리덕스는 이 데이터 저장소와 같은 역할을 합니다.

 


 

리덕스의 흐름(상태관리)

  • 스토어 구독
    • 리덕스 Store 를 components에 연결합니다.

 

  • 리듀서
    • Reducer 를 통해서 새로운 상태 값(State, Action)을 만듭니다. 

 

  • 리덕스 액션
    • Components에서 상태 변화가 필요 할때 Action 을 부른다.

 

  • 디스패치
    • Components는 새로운 상태 값(Dispatch)을 받아옵니다.

 


리덕스 용어

  • State
리덕스에 저장하고 있는 상태 값(데이터)
딕셔너리 형태  { [key]: value }  형태로 보관

  • Action
상태에 변화가 필요 할때(가지고 있는 데이터를 변경 할 때) 발생 하는 것입니다.

액션은 객체입니다. type은 이름과 같다고 생각하고 임의의 값을 입력합니다.
ex)
{ type : "CHANGE_STATE", data: {...} }

  • ActionCreator
const changeState = (new_data) => {
	// 액션을 리턴 합니다.
    return{
    	type: "CHANGE_STATE",
        data: new_data
    }
}

  • Reducer
// 초기 값 설정

const initialState = {
  name: 'jaeilit'
}

export default function reducer((state) => {
  switch (action.type) {
    case CHANGE_STATE:

      // action의 타입마다 케이스문을 걸어주면, 
		// 액션에 따라서 새로운 값을 돌려줍니다!
      return {
        name: 'jaeilit'
      }

    default:
      return state
  }
})
리덕스에 저장 된 상태(=데이터)를 변경하는 함수
1. 우리가 액션 생성 함수를 부르고
2. 액션을 만들면 
3. 리듀서가 현재상태(=state)와 액션 객체를 받아서
4. 새로운 데이터를 만들고
5. 리턴해줍니다.

  • Store
프로젝트에 리덕스를 적용하기 위해서 설정하는 것
import { combineReducers, createStore } from "redux"

// 리덕스들을 묶어주는 역할
const rootReducer = combineReducers({ "리덕스 파일명" })


// 묶은 리덕스로 store 를 생성
const store = createStore(rootReducer)

export default store​

  • Dispatch
액션을 발생 시키는 역할
// 컴포넌트에서 불러온다.

const dispatch = useDispatch()

// 디스패치를 통해서 상태 값 변경 발생
// 디스패치(리덕스 함수명(값))

const setAnswer = (user_answer) => {
    dispatch(addAnswer(user_answer))
  }

예제로 보는 리덕스

// 스토어

import { combineReducers, createStore } from "redux"
import quiz from "./modules/quiz"

const rootReducer = combineReducers({ quiz })

const store = createStore(rootReducer)

export default store

 

const ADD_ANSWER = "quiz/ADD_ANSWER"
// 리덕스 모듈


export const addAnswer = (user_answer) => {
  return { type: ADD_ANSWER, user_answer }
}

const initialState = {
  quiz_list: [
    { question: "재롱이는 1살이다.", answer: false },
    { question: "재롱이는 2살이다.", answer: false },
    { question: "재롱이는 3살이다.", answer: true },
  ],
  user_answer_list: [],
}

export default function reducer(state = initialState, action = {}) {
  switch (action.type) {
    case "quiz/ADD_ANSWER": {
    
      console.log("퀴즈액션", action) 
      
      // {type: 'quiz/ADD_ANSWER', user_answer: true}
      
      console.log("퀴즈스테이트", state)
      
       // quiz_list: (3) [{…}, {…}, {…}] ,user_answer_list: []
 
      const new_user_answer_list = [
        ...state.user_answer_list,
        action.user_answer,
      ]

      console.log("리듀서 뉴 유저", new_user_answer_list) // []
      return { ...state, user_answer_list: new_user_answer_list }
    }
    default:
      return state
  }
}
// 컴포넌트 useSelector 불러오기

const quiz_list = useSelector((state) => state.quiz.quiz_list)
// state.파일명.state

const user_answer_list = useSelector((state) => state.quiz.user_answer_list)
// state.파일명.state
 <div>
   <p>
   	<Highlight>{user_answer_list.length + 1}번 문제</Highlight>
    // 불러온 data 리덕스 사용
   </p>
   <h3>{quiz_list[user_answer_list.length].question}</h3>
   // 불러온 data 리덕스 사용
 </div>

 

728x90

'TIL' 카테고리의 다른 글

TIL(9)리덕스 순서  (0) 2021.09.28
TIL(8)Friebase  (0) 2021.09.25
TIL(6) 배열메서드 Array.map(forEach), filter, concat, from  (0) 2021.09.21
TIL4(JWT, API)  (0) 2021.09.19
TIL3(저장소Storage)  (0) 2021.09.18