공홈 자기소개
자바스크립트 앱에서 예측 가능한 상태 관리를 해주는 컨테이너 라이브러리
기본 개념
1. 동일 데이터는 항상 같은 곳에서 데이터를 가지고 온다 (single source of truth)
2. 상태는 항상 읽기 전용이다 (state is read-only)
3. 변경은 순수 함수로만 가능하다 (changes are made with pure functions)
어떠한 일이 되었든, 순서가 복잡하거나 코드가 복잡하거나 이해관계가 복잡하면 그 일은 언젠가 엎어진다.
리덕스는 데이터를 집중하여 관리하여 리액트에서 이와 관련된 코드를 압도적으로 간단하게 만들어 준다.
상태가 관리되는 오직 하나의 공간
리액트에서 state를 주고받으려면 자식 컴포넌트에서 부모 컴포넌트까지 state를 리프팅 한 다음,
state가 필요한 자식 컴포넌트까지 전달해주는 과정이 또다시 필요했다.
하지만 state를 컴포넌트에 저장하는 것이 아닌, redux store에 저장하여 정보를 가져올 수 있다
자바스크립트 객체이다. 객체 안에 다양한 데이터들이 담기는데, action객체가 store에게 애플리케이션의 데이터를 운반해주는 역할을 한다.
type은 반드시 지정해 주어야 한다.
현재 상태와 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. 필요 시 반복
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 리스트에 추가되었습니다')
}
}
dispatch
는 action
을 전달하는 메소드이다.
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
를 작성할 때, redux
의 state
업데이트는 반드시 immutable한 방식으로 변경해야 한다.(Object.assign
등)
컴포넌트와 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>
}
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>
)
}