Redux 기술공유 - woowa-techcamp-2021/store-4 GitHub Wiki

https://medium.com/@jsh901220/react에-redux-적용하기-a8e6efd745c9

https://beomy.tistory.com/35

리덕스의 정의

→ 예측 가능한 state container.

  • action 에 반응해 상태를 변경한다.

    ⇒ UI 를 상태에 대한 함수로 기술하는 react 와 궁합이 좋다.

local state vs global state

  • local state : 각 component 가 가지는 state.
  • global state : 어플리케이션 전체에서 공유하는 state. (예 : 로그인 정보)

리액트에서 상태관리가 필요한 이유

  1. local state 전파가 어렵다.
  2. global state 유지가 어렵다.

⇒ 정리하면, props 외에 데이터를 전파할 수단이 필요하다

react-redux

  • 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")
);

react + redux

1. Action

  • 어떤 변화가 일어나야 할지 알려주는 (객체?).
  • 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
	};
}

2. Reducer

  • 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;

dispatch

  • 어떤 이벤트 발생 → 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())
}

subscribe

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>
		);
	}
}
⚠️ **GitHub.com Fallback** ⚠️