TIL_Redux

멜로디·2021년 5월 17일
0

Today I Learned

목록 보기
30/30

리덕스가 무엇인가

공홈 자기소개
자바스크립트 앱에서 예측 가능한 상태 관리를 해주는 컨테이너 라이브러리

기본 개념
1. 동일 데이터는 항상 같은 곳에서 데이터를 가지고 온다 (single source of truth)
2. 상태는 항상 읽기 전용이다 (state is read-only)
3. 변경은 순수 함수로만 가능하다 (changes are made with pure functions)

그래서 리덕스가 왜 필요한가

어떠한 일이 되었든, 순서가 복잡하거나 코드가 복잡하거나 이해관계가 복잡하면 그 일은 언젠가 엎어진다.
리덕스는 데이터를 집중하여 관리하여 리액트에서 이와 관련된 코드를 압도적으로 간단하게 만들어 준다.

용어설명

store

상태가 관리되는 오직 하나의 공간
리액트에서 state를 주고받으려면 자식 컴포넌트에서 부모 컴포넌트까지 state를 리프팅 한 다음,
state가 필요한 자식 컴포넌트까지 전달해주는 과정이 또다시 필요했다.
하지만 state를 컴포넌트에 저장하는 것이 아닌, redux store에 저장하여 정보를 가져올 수 있다

action

자바스크립트 객체이다. 객체 안에 다양한 데이터들이 담기는데, action객체가 store에게 애플리케이션의 데이터를 운반해주는 역할을 한다.
type은 반드시 지정해 주어야 한다.

reducer

현재 상태와 action을 이용해 다음 상태를 만들어 낸다
데이터 흐름은 action 객체 => Dispatch => Reducer => Store(New State) 이다.
(action 객체가 dispatch라는 메소드에 전달이 되고 dispatch 메소드가 reducer를 호출해준다)

리덕스의 데이터 흐름


1. 처음 데이터를 읽어올 때에는 store에 저장된 state를 읽어서 UI에 표시해준다.
2. UI에서 event가 발생하면 Dispatch 메소드가 action 객체를 reducer에 넘긴다.
3. reducer는 전달받은 action 객체를 반영한 새로운 state를 만들고, 이걸 UI에 전달한다.
4. 필요 시 반복

redux의 장점

  1. 상태를 예측 가능하게 만들어 준다
    reducer는 순수 함수이기 때문에 다음 상태가 어떻게 될 지 쉽게 예측할 수 있다
  2. 유지보수가 용이하다
    컴포넌트끼리 데이터를 주고받는다면 버그 발견 시 관련 코드를 모조리 수정해야 하지만 redux를 사용하면 필요한 코드만 수정할 수 있다
  3. 디버깅에 유리하다
    action과 state log를 기록하면, action이 생겼을 때 어떤 일이 일어나는 지 모두 추적할 수 있다.
  4. 테스트를 붙이기 쉽다
    흐름을 알기 편하기 때문에 검증이 필요한 데이터나 흐름을 쉽게 테스트 할 수 있다.

코드 쓰는 법

store

const store = createStore(rootReducer);

모든 state가 관리되는 단일 저장소의 역할을 한다.
위 예시는 createStore 메소드를 활용해 reducer를 연결하는 방법이다.
store를 만드는 것과 더불어 다른 리듀서의 조합을 인자로 넣어 스토어를 생성할 수 있다.
실제 소스코드에서는 미들웨어와 redux devtools 연결을 위해 두번째 인자에 다른 내용이 더 들어가 있다.

action

function addTodo(text) {
  return {
    type: ADD_TODO,
    // 이 아래에 내용을 적는다
    dothiswork : // 반영할 내용
  }
}

type은 반드시 포함되어야 하는 내용이며, 그 이외의 것들은 선택적으로 사용할 수 있다.
상태에 대한 모든 변화를 action을 통해 취하는 것은, 어플리케이션에서 어떤 변화가 일어나는 지 직관적으로 알기 쉽게 하는 역할을 한다.

dispatch

const handleClick = (item) => {
  if(!todoLists.map((el) => el.todoId).includes(item.id)) {
    dispatch(notify('todo 리스트에 추가되었습니다')
  }
}

dispatchaction을 전달하는 메소드이다.
dispatch의 전달 인자로 action객체가 전달되며, reducer를 호출해 state의 값을 바꾸는 역할을 한다.

reducer

const todoReducer = (state = initialState, action) => {
  switch (action.type) {
    case ADD_TO_LIST:
      return Object.assign({}, state, {
        todoLists: [...state.todolists, action.dothiswork]
      })
    default:
      return state;
  }
}

reducer는 보통 위와 같은 코드로 구성된다. switch대신 if를 사용할 수도 있다.

주의
reducer를 작성할 때, reduxstate 업데이트는 반드시 immutable한 방식으로 변경해야 한다.(Object.assign 등)

redux hooks의 대표적인 메소드

useSelector()

컴포넌트와 state를 연결하는 역할을 한다.
컴포넌트에서 useSelector메소드를 통해 store의 state에 접근할 수 있다.

import React from 'react'
import { useSelector } from 'react-redux'

export const TodoListItem = props => {
  const todo = useSelector(state => state.todos[props.id])
  return <div>{todo.text}</div>
}

useDispatch()

action 객체를 reducer로 전달해주는 역할을 한다.
이벤트가 일어나는 컴포넌트에 사용된다.

import React from 'react'
import { useDispatch } from 'react-redux'

export const CounterComponent = ({ value }) => {
  const dispatch = useDispatch()

  return (
    <div>
      <span>{value}</span>
      <button onClick={() => dispatch({ type: 'increment-counter' })}>
        Increment counter
      </button>
    </div>
  )
}
profile
하루하루 배울때마다 기록하는 일기장

0개의 댓글