redux

Unidirectional data flow

function createStore(reducer) { var state; var listeners = []; var getState = () => state; var dispatch = (action) => { state = reducer(state, action); listeners.forEach(l=>l()); } var subscribe = (listener) => { listeners.push(listener); return () => { listeners = listeners.filter((l) => l ! = listener) } } dispatch(); return { getState, dispatch, subscribe } } var reducer = (state = 0, action) => { if (! action) return state; console.log(action); switch (action.type) { case 'INCREMENT': return state + 1; case 'DECREMENT': return state - 1; default: return state; } } var store = createStore(reducer); store.subscribe(function () { document.querySelector('#counter').innerHTML = store.getState(); }); // The listener can get the current state from store.getState(). If React is used, this will trigger a rerendering of the View. // function listerner() { // let newState = store.getState(); // component.setState(newState); // } document.querySelector('#addBtn').addEventListener('click', function () { store.dispatch({type: 'INCREMENT'}); }); document.querySelector('#minusBtn').addEventListener('click', function () { store.dispatch({type: 'DECREMENT'}); });Copy the code

Class components use React-redux

connect

import React from 'react' import { render } from 'react-dom' import { Provider } from 'react-redux' import { createStore  } from 'redux' import todoApp from './reducers' import App from './components/App' let store = createStore(todoApp) render( <Provider store={store}> <App /> </Provider>, document.getElementById('root') ) import { connect } from 'react-redux' const VisibleTodoList = connect( mapStateToProps, mapDispatchToProps )(TodoList)Copy the code

Function components use Redux

useSelector, useDispatch

import React from 'react' import { useSelector, useDispatch } from 'react-redux' import { updateTel, updateName } from './action' export default () => { const formData = useSelector(state => { console.log('--xia-', state); return state }) console.log({formData}); Const dispatch = useDispatch() return <div> form: <input type="text" onChange={(e) => {dispatch(updateName(e.target.value))}} <input type="tel" onChange={(e) => { dispatch(updateTel(e.target.value)) }}/> </div> }Copy the code

asynchronous

CNPM install –save redux-thunk

1. In store.js, introduce middleware and use it

import {createStore,applyMiddleware} from 'redux';
import thunk from 'redux-thunk'
const store=createStore(counter,applyMiddleware(thunk))
Copy the code

2. Define the action constant name in action-type and set the synchronous action associated with the asynchronous state

Export const xx=(parameter)=>{return dispatch=>{asynchronous operation, call synchronous method to change state dispatch(synchronous action method (parameter))}}Copy the code

3, introduce the corresponding variable name and other operations…

actions.js

import { INCREMENT,DECREMENT } from "./action-type"; Export const increment=(num)=>({type: increment,data:num}) export const increment Decrement =(num)=>({type: Decrement,data:num}) // Export const incrementAsync=(num)=>{return Dispatch =>{ setTimeout(()=>{ dispatch(increment(num)) },1000) }}Copy the code

store.js:

import {createStore,applyMiddleware} from 'redux'; import {counter} from './reducers' import thunk from 'redux-thunk' const Store =createStore(counter,applyMiddleware(thunk))// The second parameter specifies the middleware console.log(store) on the app; export default store;Copy the code

app.js

import React from 'react'; import './App.css'; import {increment,decrement,incrementAsync} from './redux/actions' import PropTypes from 'prop-types' import {connect} from 'react-redux' class App extends React.Component{ static propTypes={ count:PropTypes.number.isRequired, increment:PropTypes.func.isRequired, decrement:PropTypes.func.isRequired, incrementAsync:PropTypes.func.isRequired } increment = () => { const num = this.refs.numSelect.value*1 // this.props.store.dispatch(actions.increment(num)); this.props.increment(num); } decrement = () => { const num = this.refs.numSelect.value*1 // this.props.store.dispatch(actions.decrement(num)) this.props.decrement(num); } incrementIfOdd = () => { const num = this.refs.numSelect.value*1 // const count=this.props.store.getState(); const count=this.props.count if(count%2==1) { this.props.increment(num); }} / / asynchronous invocation incrementAsync = () = > {const num = this. Refs. NumSelect. Value * 1 this props. IncrementAsync (num); } render () { // const count = this.props.store.getState() const count =this.props.count; return ( <div> <p> click {count} times {' '} </p> <select ref="numSelect"> <option value="1">1</option> <option value="2">2</option> <option value="3">3</option> </select>{' '} <button onClick={this.increment}>+</button>{' '} <button onClick={this.decrement}>-</button>{' '} <button onClick={this.incrementIfOdd}>increment if odd</button>{' '} <button onClick={this.incrementAsync}>increment async</button> </div> ) } } export default connect( state=>({ count:state }), {increment,decrement,incrementAsync} )(App); // Connect () returns a class with the first parameter as a function, the second parameter as an object, and the received parameter as an App component. The deconstruction is passed as a parameter to the component AppCopy the code