독립적
)npm install || yarn add redux react-redux
Store
, 상태 저장소에 접근을 위한 reducer
, 리듀서에 행동을 지시하는 action
, 저장소에 보관된 상태를 가져오는 subscription
으로 나뉘어져 있다index.js
에 정의한다createStore : 저장소 생성
<Provider store={store}>
"복사"
하여 상태를 갱신한 후에 반환해야 한다 !절대로 기존상태를 직접 조작하면 안된다!dispatch() 함수를 이용
한다데이터를 실어보낼 수도 있다
combineReducers
를 이용할 수 있다createStore(combineReducers({ reducer, reducer2 }))
react-redux 라이브러리에서 제공하는 Hooks(use...)과 HOC(connect)가 있다
const store = useStore()
useSelector(selector : Function, deps : any[])
const dispatch = useDispatch()
export default connect(connect함수명)(Component명)
// 예시
// store/index.js 정의
import { createStore } from 'redux';
const initialState = { counter: 0, showCounter: true };
const counterReducer = (state = initialState, action) => {
if (action.type === 'increment') {
return {
counter: state.counter + 1,
showCounter: state.showCounter,
// 데이터가 추가되는것이 아닌 덮어씌어지기때문에 값의 변화가 없더라도 명시해야한다
};
}
if (action.type === 'increase') {
return {
counter: state.counter + action.amount, // 데이터를 받아올수도 있다
showCounter: state.showCounter,
};
}
if (action.type === 'decrement') {
return {
counter: state.counter - 1,
showCounter: state.showCounter,
};
}
if (action.type === 'toggle') {
return {
counter: state.counter,
showCounter: !state.showCounter,
};
}
return state;
};
const store = createStore(counterReducer);
export default store;
// src/index.js 정의
import React from 'react';
import ReactDOM from 'react-dom';
import { Provider } from 'react-redux';
import App from './App';
import store from './store/index';
ReactDOM.render(
<Provider store={store}>
<App />
</Provider>,
document.getElementById('root')
);
// 최종전달 컴포넌트
import { useSelector, useDispatch } from 'react-redux';
const Counter = () => {
const dispatch = useDispatch();
const counter = useSelector(state => state.counter);
const show = useSelector(state => state.showCounter);
const incrementHandler = () => {
dispatch({ type: 'increment' });
};
const increaseHandler = () => {
dispatch({ type: 'increase', amount: 5 });
};
const decrementHandler = () => {
dispatch({ type: 'decrement' });
};
const toggleCounterHandler = () => {
dispatch({ type: 'toggle' });
};
return (
<main>
<h1>Redux Counter</h1>
{show && <div className={classes.value}>{counter}</div>}
<div>
<button onClick={incrementHandler}>Increment</button>
<button onClick={increaseHandler}>Increment by 5</button>
<button onClick={decrementHandler}>Decrement</button>
</div>
<button onClick={toggleCounterHandler}>Toggle Counter</button>
</main>
);
};
// 최종전달 컴포넌트 class형으로 변환
import { Component } from 'react';
import { connect } from 'react-redux';
class Counter extends Component {
incrementHandler() {
this.props.increment();
}
decrementHandler() {
this.props.decrement();
}
render() {
return (
<main>
<h1>Redux Counter</h1>
<div>{this.props.counter}</div>
<div>
<button onClick={this.incrementHandler.bind(this)}>Increment</button>
<button onClick={this.decrementHandler.bind(this)}>Decrement</button>
</div>
</main>
);
}
}
const mapStateToProps = state => {
return {
counter: state.counter,
};
};
const mapDispatchToProps = dispatch => {
return {
increment: () => dispatch({ type: 'increment' }),
decrement: () => dispatch({ type: 'decrement' }),
};
};
export default connect(mapStateToProps, mapDispatchToProps)(Counter);