This is an old revision of the document!
Redux
- Install redux, react-redux, and update the react-dom
- Create a reducer for storing the state, and handle the dispatched task
- Create the store in index.js, and provide it to the app by <Provider…></Provider>
- In your component, create mapStateToProps, and mapDispatchToProps. Then use import {connect} from 'react-redux'; to connect your component to the store.
Install
npm install react react-redux npm update react react-dom
Create Reducer
create a file call reducer.js
, put in under /src/store/. We also put the initial state there.
const initialState = { counter: 0 } const reducer = (state = initialState, action) => { switch (action.type) { case 'INCREMENT': return { ...state, counter: state.counter + 1 } case 'DECREMENT': return { ...state, counter: state.counter - 1 } case 'INCREMENT5': return { ...state, counter: state.counter + action.value } case 'DECREMENT5': return { ...state, counter: state.counter - action.value } default: return state; } } export default reducer;
Create Store in index.js, and Provider it to the app
Here we create the store by using createStore, passing out reducer to it. Finally provide it to the app by <Provider store={…}…></Provider>
import React from 'react'; import ReactDOM from 'react-dom'; import './index.css'; import App from './App'; import registerServiceWorker from './registerServiceWorker'; import {createStore} from "redux"; import reducer from "./store/reducer"; import {Provider} from 'react-redux'; const store = createStore(reducer); ReactDOM.render( <Provider store={store}> <App/> </Provider>, document.getElementById('root')); registerServiceWorker();
Connect Out Component to it
The key here is to create a mapStateToProps
to get the state from redux, and a mapDispatchToProps
to dispatch actions to the redux. We connect redux to our component by using export default connect(mapStateToProps, mapDispatchToProps)(Counter); at the end.
Since the state and action are now the props, we can use them and call them in our component like 'this.props….
The 'action' we dispatch usual has a
type'' for the type of action, and any addition fields if needed.
import React, {Component} from 'react'; import CounterControl from '../../components/CounterControl/CounterControl'; import CounterOutput from '../../components/CounterOutput/CounterOutput'; import {connect} from 'react-redux'; class Counter extends Component { render() { return ( <div> <CounterOutput value={this.props.ctr}/> <CounterControl label="Increment" clicked={this.props.onIncrementCount}/> <CounterControl label="Decrement" clicked={() => this.props.onDecrementCount()}/> <CounterControl label="Add 5" clicked={() => this.props.onInc5Count()}/> <CounterControl label="Subtract 5" clicked={() => this.props.onDec5Count()}/> </div> ); } } const mapStateToProps = state => { return { ctr: state.counter } }; const mapDispatchToProps = dispatch => { return { onIncrementCount: () => dispatch({type: 'INCREMENT'}), onDecrementCount: () => dispatch({type: 'DECREMENT'}), onInc5Count: () => dispatch({type: 'INCREMENT5', value:5}), onDec5Count: () => dispatch({type: 'DECREMENT5', value:10}), }; } export default connect(mapStateToProps, mapDispatchToProps)(Counter);
The action.type needs to match the one in the reducer! Any spelling mistake/mismatch would cause the reducer to do nothing. You might want to use a separated file, and include this file on both the reducer and the component.