====== 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 - Using redux in your component: - Class-based component: In your component, create mapStateToProps, and mapDispatchToProps. Then use import {connect} from 'react-redux'; to connect your component to the store. - Functional-based component: Use {useSelector, useDispatch} from 'react-redux'. ''useSelector'' obtains the values, and ''useDispatch'' dispatches the actions. ===== 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 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( , document.getElementById('root')); registerServiceWorker(); ===== Connect Out Component to it ===== ==== Old Way: For Class Base Component ==== 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 (
this.props.onDecrementCount()}/> this.props.onInc5Count()}/> this.props.onDec5Count()}/>
); } } 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. ==== New Way: Use Hooks For Functional Base Component ==== People in these days use functional base component for react, and here is how to use redux in it by using ''useSelector'', ''useDispatch'' and hooks. import './App.css'; import {useSelector, useDispatch} from 'react-redux' function App() { const count = useSelector(state => { return state.counter; } ) const dispatch = useDispatch(); const click = (action, value) => { if (value) { dispatch({type: action, value: value}); } else { dispatch({type: action}); } } return ( <>
The counter is: {count}
) } export default App;