액션
{ type: .... , payload: ... } 구조의 객체이다.
type - 액션이 어떤 작업인지 쉽게 이해할 수 있는 고유한 값을 구분한 문자열
payload - 스토어에 사용할 값으로 스토어의 데이터를 초기화하는 경우에는 생략 가능
{
type: 'SET_LOADING',
payload: true,
}
리듀서
//기본 함수 구조
function reducer(state, action) { return state;}
//사용 예시 , 이전 데이터(state)를 받아 새로운 데이터(sate.payload)로 변경
const reducer = (state, action) => state + action.payload;
스토어의 이전 데이터, 액션을 받아 새로운 스토어의 데이터를 반환한다.
반환하는 값의 자료형은 스토어의 이전 데이터와 동일해야 한다.
리듀서 실행 방식
예시)
class Store {
state = {};
//action이 dispatch()함수의 인자로 할당
dispatch(action){
const reducer1 = state => state;
const reducer2 = (state), action) => state + action.payload;
...
const reducers = [reducer1, reducer2, ...];
//리듀서함수들은 reduce()함수에 의해 변경된 새 스토어의 객체로 변환
const updatedState = reducers.reduce(
(nextState, reducer) => reducer(nextState, action),
this.state,
);
//변경된 객체로 스토어의 원본을 교체
this.state = updatedState;
//이후 다른 컴포넌트로 새 state전달하는 과정
}
}
dispatch()함수
액션을 리듀서로 전달시키는 함수이다.
사용예시)
아래 코드의 componentDidMount()함수 안에서 { type: 'SET_LOADING', payload: true, } 액션이 dispatch() 함수를 통해서 리듀서에 전달되는 것을 볼 수 있다.
import React, { PureComponent } from 'react';
import { createStore } from 'redux';
import { Provider } from 'react-redux';
class ReduxApp extends PureComponent {
store = createStore(
state => state,
{ loading: false, name: '두잇 리액트' },
window.__REDUX_DEVTOOLS_EXTENSION__ && window.__REDUX_DEVTOOLS_EXTENSION__(),
);
componentDidMount() {
this.store.dispatch({
type: 'SET_LOADING',
payload: true,
});
}
render() {
return <Provider store={this.store}>리덕스 예제</Provider>;
}
}
export default ReduxApp;
크롬 리덕스 확장도구 메뉴에서
[Action] - Action의 상세 내용을 알려준다
[State] - 리듀서에 전달된 액션에 의해 바뀐 스토어 데이터를(state) 알려준다
[Diff] - 이전 state와 현재 state를 비교해여 알려준다
리듀서 / 액션 분리하기
리듀서나 액션을 데이터의 종류에 맞게 분리하는 것이 코드를 효율적으로 관리하기에 알맞은 방법이다.
리듀서 분리하기
1. 리듀서를 각각의 파일로 분리하기
loading, user, collection 리듀서를 각각의 파일로 분리한다.
2. 리듀서 묶어주기
분리한 리듀서가 하나처럼 작동하기 위해서는 각 리듀서를 묶어 익스포트 해줘야 한다.
index.js파일)
import loading from './loadingReducer';
import user from './userReducer';
import collection from './collectionReducer';
import searchFilter from './searchFilterReducer';
export default {
collection,
loading,
user,
searchFilter,
};
3. 스토어 설정 파일 만들기
여러 개의 리듀서는 combineReducers()함수로 묶어 createStore()함수의 인자로 전달한다.
composeWithDevTools는 리덕스 크롬확장 도구를 사용하기 위해서 추가한 것이고 , createStore()함수의 미들웨어 인자로 전달했다.
import { createStore, combineReducers } from 'redux';
import { composeWithDevTools } from 'redux-devtools-extension';
import reducers from './reducers';
export default initStates => createStore(
combineReducers(reducers),
initStates,
composeWithDevTools(),
);
4. 리액트 앱 다시 구성하기
발생 문제1.
Error: Reducer "loading" returned undefined during initialization ...
해결
=> 리듀서의 state인자 초깃값을 수정하고 다시 앱을 구동한다.
발생 문제2.
리덕스 크롬 확장도구에서 확인할 수 있는 이중 키 구조 문제
해결
=> 만약 loading리듀서라는 리듀서의 이중키 구조가 문제가 된다하면 loading리듀서가 loading이라는 키 이름을 제외한 값만 반환하도록 수정한다. 액션의 경우마다 반환값이 객체가 아닌 값(true, false)로 바꾼다.
'Tech > ReactJS' 카테고리의 다른 글
[ReactJS 기초] VanillaJS와 ReactJS 비교 (0) | 2022.05.17 |
---|---|
[React] 그래프 데이터베이스 (0) | 2021.07.16 |
[React] 리덕스 개념 / 기초 (0) | 2021.07.16 |
[React] 컨텍스트 API 활용 (0) | 2021.07.16 |
[React] 중복 공급자 개념 / 문제 (0) | 2021.07.16 |