Redux 기술공유 - woowa-techcamp-2021/store-4 GitHub Wiki
https://medium.com/@jsh901220/react에-redux-적용하기-a8e6efd745c9
→ 예측 가능한 state container.
-
action 에 반응해 상태를 변경한다.
⇒ UI 를 상태에 대한 함수로 기술하는 react 와 궁합이 좋다.
local state vs global state
- local state : 각 component 가 가지는 state.
- global state : 어플리케이션 전체에서 공유하는 state. (예 : 로그인 정보)
- local state 전파가 어렵다.
- global state 유지가 어렵다.
⇒ 정리하면, props 외에 데이터를 전파할 수단이 필요하다
- dispatch 를 ⇒ props 로 매핑.
- store 의 state 를 ⇒ props 로 매핑.
import React, { Component } from 'react';
import { connect } from 'react-redux';
import { setDiff } from '../actions';
class Option extends Component {
constructor(props) {
super(props);
this.onChange = this.onChange.bind(this);
}
onChange(event) {
this.props.onUpdateDiff(parseInt(event.target.value));
}
render() {
return (
<div>
<input value={this.props.diff} onChange={this.onChange} />
</div>);
}
}
let mapStateToProps = (state) => {
return {
diff: state.counter.diff
}
}
let mapDispatchToProps = (dispatch) => {
return {
onUpdateDiff: (value) => dispatch(setDiff(value))
};
}
Option = connect(mapStateToProps, mapDispatchToProps)(Option);
export default Option;
import { createStore } from "redux";
import { Provider } from "react-redux";
const store = createStore(counterApp);
ReactDOM.render(
<Provider store={store}>
<App />
</Provider>,
document.getElementById("root")
);
- 어떤 변화가 일어나야 할지 알려주는 (객체?).
- type 이 필수적으로 포함. ⇒ action 을 구분하는 ID.
export const INCREMENT = 'INCREMENT';
export const DECREMENT = 'DECREMENT';
export const SET_DIFF = 'SET_DIFF';
export function increment() {
return {
type: INCREMENT
};
}
export function decrement() {
return {
type: DECREMENT
};
}
export function setDiff(value) {
return {
type: SET_DIFF,
diff: value
};
}
- action 을 건네받아 state 를 변경.
import { INCREMENT, DECREMENT, SET_DIFF } from "../actions";
import { combineReducers } from "redux";
const counterInitialState = { value: 0, diff: 1 };
const counter = (state = counterInitialState, action) => {
switch (action.type) {
case INCREMENT:
return Object.assign({}, state, { value: state.value + state.diff });
case DECREMENT:
return Object.assign({}, state, { value: state.value - state.diff });
case SET_DIFF:
return Object.assign({}, state, { diff: action.diff });
default:
return state;
}
};
const counterApp = combineReducers({ counter });
export default counterApp;
- 어떤 이벤트 발생 → store.dispatch(action) → reducer 가 state 변경.
onChange(event) {
this.props.store.dispatch(setDiff(parseInt(event.target.value)));
}
onIncrement(event) {
this.props.store.dispatch(increment())
}
onDecrement(event) {
this.props.store.dispatch(decrement())
}
const store = createStore(counterApp);
const render = () => {
ReactDOM.render(<App store={store} />, document.getElementById("root"));
};
store.subscribe(render);
render();
render() {
return (
<div>
<input value={this.props.store.getState().counter.diff} onChange={this.onChange} />
</div>
);
}
- store 를 props 로 계속 넘겨주어야한다.
- boilerplate 코드가 많다.
class App extends Component {
render() {
return (
<div>
<Counter store={this.props.store} />
<Option store={this.props.store} />
<Button store={this.props.store} /> </div>
);
}
}