
이미지출처: https://opentutorials.org/module/4078/24935
dispatch(action creator) → reducer(action) → store(reducer) → subscribe() → getState()
let store = Redux.createStore(reducer);
function reducer(state, action) {
// state의 초기값을 color:'yellow'로 설정 설정
if (state === undefined) {
return {color:'yellow'}
}
let newState;
if (action.type === 'CHANGE_COLOR') {
// 빈 객체에 기존 state와 {color:action.color}를 덮어 씌워 newState에 초기화
newState = Object.assign({}, state, {color:action.color});
}
return newState;
}
// 덮어질 객체에 덮어씌울 객체를 덮어 씌운 뒤 덮어질 객체를 반환
Object.assign({덮어질 객체}, {덮어씌울 객체}, ...)
let state = store.getState()
console.log(state);
// {color: "yellow"}
console.log(state.color);
// "yellow"
store.dispatch({type:'CHANGE_COLOR', color:'red'});
// action = {type:"CHANGE_COLOR", color:"red"}
// 버튼을 클릭하면 dispatch를 통해 action을 reducer에 전달
function red() {
document.querySelector('#red').innerHTML = `
<div class="container" id="component_red">
<h1>red</h1>
<input type="button" value="fire" onclick"
store.dispatch({type:'CHANGE_COLOR', color:'red'});
">
</div>
`;
}
red()
// red 함수를 구독 상태로
store.subscribe(red);

npm install redux
npm install react-redux
import React, { useState } from 'react';
import { createStere } from 'redux';
import { Provider, useSelector, useDispatch, connect } from 'react-redux'
[applyMiddleware()](https://ko.redux.js.org/api/applymiddleware)const store = createStore(reducer);
// reducer 에서 받아온 state 를 변수 store 에 초기화
// Provider 에서 store 를 통해 useSelector 에게 넘겨줄 예정
function reducer(currentState, action) {
if (currentState === undefined)
{ //현재 상태가 undefined(정의되지 않음) 라면 {number: 1} 리턴
return {
number: 1,
};
}
const newState = { ...currentState }; //과거 상태를 newState에 복제 후 리턴
if (action.type === 'PLUS') {
//useDispatch로 부터 받은 action.type이 'PLUS 라면 number 에 1을 더해줌
newState.number++;
}
return newState;
}
function App() {
const [number, setNumber] = useState(1); //상태 초기값은 1
return (
<div id="container">
<h1>Root</h1>
<div id="grid">
<Provider store={store}>
<Left1></Left1>
<Right1></Right1>
</Provider>
</div>
</div>
);
}
//Left1과 Right1에 state를 제공
function Left3(props) {
// 전달받은 state 값중 number를 쓰겠다는 의미
const number = useSelector((state) => state.number);
return (
<div>
<h1>Left3 : {number}</h1>
</div>
);
}
function Right3(props) {
const dispatch = useDispatch(); //useDispatch() 선언
return (
<div>
<h1>Right3</h1>
<input type="button" value="+" onClick={() => {
dispatch({ type: 'Plus' })
//reducer 함수의 두번째 인자에 { type: 'PLUS'}
}}>
</input>
</div>
);
}

Right3 의 버튼을 누르면 left3 의 count 가 증가
import React, { useState } from 'react';
import './style.css';
import { createStore } from 'redux';
import { Provider, useSelector, useDispatch, connect } from 'react-redux';
function reducer(currentState, action) {
if (currentState === undefined) {
return {
number: 1,
};
}
const newState = { ...currentState };
if (action.type === 'PLUS') {
newState.number++;
}
return newState;
}
const store = createStore(reducer);
export default function App() {
const [number, setNumber] = useState(1);
return (
<div id="container">
<h1>Root</h1>
<div id="grid">
<Provider store={store}>
<Left1></Left1>
<Right1></Right1>
</Provider>
</div>
</div>
);
}
function Left1(props) {
return (
<div>
<h1>Left1 </h1>
<Left2></Left2>
</div>
);
}
function Left2(props) {
return (
<div>
<h1>Left2 : </h1>
<Left3></Left3>
</div>
);
}
function Left3(props) {
const number = useSelector((state) => state.number);
return (
<div>
<h1>Left3 : {number}</h1>
</div>
);
}
function Right1(props) {
return (
<div>
<h1>Right1</h1>
<Right2></Right2>
</div>
);
}
function Right2(props) {
return (
<div>
<h1>Right2</h1>
<Right3></Right3>
</div>
);
}
function Right3(props) {
const dispatch = useDispatch();
return (
<div>
<h1>Right3</h1>
<input type="button" value="+" onClick={() => {
dispatch({ type: 'Plus' })
}}></input>
</div>
);
}
npm install @reduxjs/toolkit
import React from 'react';
import { useSelector, useDispatch, Provider } from 'react-redux';
import store from './store';
import { up } from './counterSlice';
function Counter() {
const dispatch = useDispatch();
// useSelector
// state = configureStore의 reducer
// state.counter = counterSlice.reducer
// counterSlice.reducer = counterSlice의 reducer이 return 하는 state
// counsterSlice.reducer의 state의 key는 현재 value
const count = useSelector((state) => {
return state.counter.value;
});
return (
<div>
<button
// useDispatch
// reducer 에게 전달
onClick={() => {
// dispatch({type:'counterSlice/up', payload:2});
// counterSlice.js 내의 이름이 counterSlice인 slice
// {type: name/reducers의 key, payload: action.payload}
dispatch(counterSlice.actions.up(2));
}}
>
+
</button>{' '}
{count} //useSelector의 return값
</div>
);
}
export default function App()
return (
// Provider
// store 전달
<Provider store={store}>
<div>
<Counter></Counter>
</div>
</Provider>
);
}
import {createSlice} from '@reduxjs/toolkit';
// 필요한 Slice 만들기
// ex)timerSlice
// console.log(counterSlice);
// {
// name: 'counterSlice',
// actions: {up},
// getInitialState: f,
// reducer: f
// }
const counterSlice = createSlice({
name:'counterSlice',
// createSlice가 유니크한 action 이름을 만들어줌, action creater
initialState:{value:0},
reducers:{
up:(state, action)=>{
// createSlice를 사용하면 reducer에서 return과 ...state를 사용할 필요 없음
// console.log(action) // {type: 카운터 슬라이스의 name/up, payload:2}
state.value = state.value + action.payload;
}
}
});
export default counterSlice;
export const {up} = counterSlice.actions;
// up 은 action creator
// createSlice에서 reducers를 정의하면,
// 각 Reducer 함수의 이름 자체가 Action Creator가 된다.
import {configureStore} from '@reduxjs/toolkit';
import counterSlice from './counterSlice';
const store = configureStore({
//각각 Slice의 reducer들의 집합
reducer:{
counter:counterSlice.reducer
// counterSlice의 reducers의 return 모음
});
export default store;
dispatch 함수에 액션 함수를 넘겨주면, 알아서 dispatch 함수를 액션 함수의 반환 함수의 인자로 넣고 실행.
dispatch() 안에 함수의 return 이 async 함수이면 async의 매개변수에 dispatch를 받아올 수 있는 것인가?