반응형
npm i redux
Action
- 액션은 그냥 객체이다.
- 두가지 형태의 액션
- { type : ‘TEST’} // payload없는 액션
- { type: ‘TEST’, params : ‘hello’ } // payload 있는 액션
- type만이 필수 프로퍼티이며, type은 문자열이다.
액션 생성자
사용 방법
function 액션 생성자(...args) { return 액션; }
- 액션 생성자를 통해 액션을 만들어 낸다.
- 만들어낸 액션 객체를 redux store에 보낸다.
- redux store가 액션 객체를 받으면 스토어의 상태 값이 변경된다.
- 변경된 상태 값에 의해 상태를 이용하고 있는 컴포넌트가 변경된다.
- 액션은 스토어에 보내는 일종의 인풋
액션 객체 만들기 action.js
export const ADD_TODO = "ADD_TODO"
export function addTodo(todo) {
return {
type: ADD_TODO,
todo,
};
}
//action 객체 생성
Reducers
- 액션을 주면 액션이 적용되어 수정된 결과를 만들어 준다.
- 순수 함수 (pure Function) 이다.
- immutable > reducer를 통해서 state가 달라졌다는걸 redux가 인지하는 방식이다.
사용 방법
function 리듀서(previousState, action) {
return newState;
}
action을 받아서 state를 리턴
인자로 들어온 previousState와 리턴되는 newState는 다른 참조를 가져야 한다.
리듀서 만들기 reducers.js
import { ADD_TODO } from './actions';
//state 구상하자면 ?
// ['하이','난 지니'];
const initialState = [];
export function todoApp(previousState = initialState, action) {
//초기값 지정 해주는 부분 >> '= initialState'으로 대체
// if(previousState === undefined){
// return [];
// }
if(action.type === ADD_TODO){
return [...previousState, action.todo];
}
return previousState;
}
createStore
const store = createStore(리듀서);
//인자 3개
createStore(reducer함수, preloadedState,enchancer);
import { createStore } from 'redux'
import { todoApp } from './reducers'
const store = createStore(todoApp);
export default store;
store
을 index.js
에서 출력해보면?
dispach, getState 등등의 값이 나온다.
getState : 현재의 state의 상태
dispatch: action을 인자로 가지고 있음
index.js
const unsubscribe = store.subscribe(() => {
console.log(store.getState());
})
console.log(store);
store.dispatch(addTodo('jieun'));
unsubscribe();
store.dispatch(addTodo('hihi'));
subscribe
- 스토어의 변경사항 생기는 것을 구독!
- 스토어 상태 변경되면 호출된다.
- 함수는 리턴이 함수인데 호출을 하면 더 이상 subscribe 함수에 출력되지 않는다.
store 정리
- store.getState();
- 현재 state를 가져옴
- store.dispatch(액션); / store.dispatch(액션생성자());
- const unsubscribe = store.subscribe(()⇒{});
- 리턴이 unsubscribe이다.
- unsubscribe()하면 제거된다.
- store.replaceReducer(다른리듀서);
- 원래 리듀서를 다른 리듀서로 바꾼다. > 잘 안쓰임
combineReducers
객체로 전달된 state값들중 하나를 false> true 로 변경하는 작업 해보기
state 형태
{
todos: [{text: '공부' , done: false}, {text}: '점심' , done: true}] ,
filter: 'ALL'
}
acions.js
export const ADD_TODO = "ADD_TODO"
export const COMPLETE_TODO = 'COMPLETE_TODO';
// {type : ADD_TODO , text: '할일'}
export function addTodo(text) {
return {
type: ADD_TODO,
text,
};
}
// {type : COMPLETE_TODO , index: 3} > 완성된 index 값
export function completeTodo(index) {
return {
type: COMPLETE_TODO,
index,
};
}
export const SHOW_ALL = 'SHOW_ALL';
export const SHOW_COMPLETE = 'SHOW_COMPLETE';
export function showAll() {
return {type:SHOW_ALL};
}
export function showComplete() {
return {type: SHOW_COMPLETE,};
}
reducers.js
import { ADD_TODO, COMPLETE_TODO , SHOW_COMPLETE , SHOW_ALL } from './actions';
//state 구상
//{
//todos: [{text: '공부' , done: false}, {text}: '점심' , done: true}] ,
//filter: 'ALL'
//}
// 객체로 변경
const initialState = { todos: [] , filter: 'ALL' };
export function todoApp(previousState = initialState, action) {
if(action.type === ADD_TODO){
return {
...previousState,
todos: [...previousState.todos, {text: action.text, done: false}],
};
}
if(action.type === COMPLETE_TODO){
return {
...previousState,
todos: previousState.todos.map((todo, index) => {
if(index === action.index){
return {...todo, done: true};
}
return todo;
})};
}
if(action.type === SHOW_COMPLETE){
return {
...previousState,
filter : "COMPLETE",
};
}
if(action.type === SHOW_ALL){
return {
...previousState,
filter : "ALL",
};
}
return previousState;
}
store.js
import { createStore } from 'redux'
import { todoApp } from './reducers'
const store = createStore(todoApp);
export default store;
index.js
import React from 'react';
import ReactDOM from 'react-dom';
import './index.css';
import App from './App';
import reportWebVitals from './reportWebVitals';
import store from './redux/store';
import { addTodo, completeTodo, showAll, showComplete } from './redux/actions'
//스토어의 변경사항 생기는 것을 구독!
//스토어 상태 변경되면 호출된다.
store.subscribe(() => {
console.log(store.getState());
})
store.dispatch(addTodo('할일'));
store.dispatch(completeTodo(0));
store.dispatch(showComplete());
store.dispatch(showAll());
reducer > 단일 스토어여서 여러개 둘수도 없고, 복잡해진다. 그래서 쪼개서 작업 하기
이것을 도와주는게 combineReducer 이다.
reducers.js
import { ADD_TODO, COMPLETE_TODO , SHOW_COMPLETE , SHOW_ALL } from './actions';
import { combineReducers } from 'redux'
//state 구상
//{
//todos: [{text: '공부' , done: false}, {text}: '점심' , done: true}] ,
//filter: 'ALL'
//}
// 객체로 변경
const initialState = { todos: [] , filter: 'ALL' };
const todosInitialState = initialState.todos;
const filterInitialState = initialState.filter;
const reducer = combineReducers({
todos: todosReducer,
filter: filterReducer
})
export default reducer;
//todos: [{text: '공부' , done: false}, {text}: '점심' , done: true}]
export function todosReducer(previousState = todosInitialState, action) {
if(action.type === ADD_TODO){
return [...previousState, {text: action.text, done: false}];
}
if(action.type === COMPLETE_TODO){
return previousState.map((todo, index) => {
if(index === action.index){
return {...todo, done: true};
}
return todo;
});
}
return previousState;
}
//filter: 'ALL'
function filterReducer(previousState = filterInitialState, action) {
if(action.type === SHOW_COMPLETE){
return "COMPLETE";
}
if(action.type === SHOW_ALL){
return "ALL";
}
return previousState;
}
stores.js
import { createStore } from 'redux'
import todoApp from './reducers'
const store = createStore(todoApp);
export default store;
요래 수정하기
더 간결하게 만들기 (파일 분리)
이렇게 파일 분리하기
reducer.js
import { combineReducers } from 'redux'
import todos from './todos'
import filter from './filter'
const reducer = combineReducers({
todos,
filter
})
export default reducer;
todos.js
import { ADD_TODO, COMPLETE_TODO } from '../actions';
const initialState = []
export default function todos(previousState = initialState, action) {
if(action.type === ADD_TODO){
return [...previousState, {text: action.text, done: false}];
}
if(action.type === COMPLETE_TODO){
return previousState.map((todo, index) => {
if(index === action.index){
return {...todo, done: true};
}
return todo;
});
}
return previousState;
}
filter.js
import { SHOW_COMPLETE , SHOW_ALL } from '../actions';
const initialState = 'ALL';
export default function filter(previousState = initialState, action) {
if(action.type === SHOW_COMPLETE){
return "COMPLETE";
}
if(action.type === SHOW_ALL){
return "ALL";
}
return previousState;
}
store.js
import { createStore } from 'redux'
import todoApp from './reducers/reducer'
const store = createStore(todoApp);
export default store;
완성~
반응형
'개발(라이브러리,프레임워크) > react.js & react native' 카테고리의 다른 글
Async Action (0) | 2022.01.31 |
---|---|
Redux 를 React에 연결(라이브러리x) (0) | 2022.01.21 |
Hooks (0) | 2022.01.09 |
라우팅 (0) | 2021.09.26 |
컴포넌트 (0) | 2021.09.24 |