Redux and combine React

  When Redux and React engagement Redux is the use of state management, use React development page UI. Compared to traditional html, using React to develop pages, it does bring many benefits, component-based, code reuse, but when and Redux bonding, component has also brought some problems, components nested layers, success one thousand hundreds, and store really is only one component in how to get to the store? page UI is to display the status of the application, if the acquisition can not store the state, it can not render the content. Another problem is that if the state has changed, components, how do real-time monitoring, real-time display the latest status?

  For the first question, React assembly how to get store, you might think, at the outermost component of the overall application layers of the store passed down as props for a small program, can also be accepted, but a large program it is impossible to hundreds or thousands of components are written on the store property right. Another solution is the context, all the components are included in a context, context provided store property, so do not pass the layers and all the components will get to store., Program a try

  For the second question, the internal components that you want displayed in real time up to date, it would have to use store.subscribe () method, register a listener function at its inside, get the latest status, and then injected into the assembly, component update method, that is, call setState () method, then each of our components have become stateful components. That store.subsribe () method, when a registered listener function, you must load the components necessary to complete registration, componentDidMounted in calling store.subscribe ().

  Based on the above analysis points, trying to write the code, not try to achieve engagement of Redux and React, use create-react-app to create a project react-redux-demo, then cd react-redux-demo && npm i bootstrap redux --save installation boostrap and redux. Open the project, introduced in boostrap in index.js. 

import React from 'react';
import ReactDOM from 'react-dom';
import './index.css';
import App from './App';
import 'bootstrap/dist/css/bootstrap.css'; // 添加bootstrap 样式

ReactDOM.render(<App />, document.getElementById('root'));

  Or the most simple addition and subtraction counter start, click add plus one, minus one minus click, click reset reset. Look Redux, Redux is due to the action, reducer, store, and that the relationship did not React, so completely to create action, create stroe content written in a separate file, exposing only thing React need to call it just fine. React need to store, need action, because it wants to dispatch action to change the status. For simplicity, the redux related content into a file, create a new file in the src directory redux.js

import {createStore} from 'redux';
//
state const initialState = { counter: 5 }; // action const add = { type: 'ADD' }; const minus = { type: 'MINUS' }; const reset = { type: 'RESET' }; // reducer function counter(state = initialState, action) { switch(action.type) { case 'ADD': return { ...state, counter: state.counter + 1 } case 'MINUS': return { ...state, counter: state.counter - 1 } case 'RESET': return {          ...state,           counter: 5        }; default: return state; } } // 创建store const store =createstore (counter); //store and export out Action export {store, the Add, minus, RESET};

  Now you must write React, create pages ui, the first matter interaction, first page three buttons and status display drawn, create a ThreeButton.js under src, 

import React, { Component } from 'react'

export default class ThreeButton extends Component {
    render() {
        return (
            <div style={{textAlign: "center"}}>
                <h1 id="counter">0</h1>
                <button type="button" className="btn btn-primary" style={{marginRight: '10px'}}>Add</button>
                <button type="button" className="btn btn-success" style={{marginRight: '10px'}}>Minus</button>
                <button type="button" className="btn btn-danger">Reset</button>
            </div>
        )
    }
}

  It is then introduced in App.js

import React from 'react';
import ThreeButton from './ThreeButton';

function App() {
  return (
    <ThreeButton></ThreeButton>
  );
}

export default App;

   Preparation and realization engages React Redux achieve interactive pages. First, it is to store injected into the React using context api React of most use to start context is to use createContext create a context, a new storeContext.js in the src directory

import React from 'react';
const storeContext = React.createContext({store: {}}) 
export {storeContext};

  storeContext have a property Provider, it is a component, has a value property, providing real component sharing data, this is a store Redux created. Provider then wrap the assembly, the assembly and its sub-components are shared data can be acquired, then the App wrap, and then to store the Redux storeContext.js incorporated in index.js

import React from 'react';
import ReactDOM from 'react-dom';
import './index.css';
import App from './App';
import 'bootstrap/dist/css/bootstrap.css'; // 添加bootstrap 样式

import { store } from './redux'; // 引入 store
 import { storeContext } from './storeContext'; // 引入storeContext

// provide sotre as shared data, App subassembly can be acquired and Store const Provider = <storeContext.Provider {{value = Store: Store}}> <the App /> </storeContext.Provider> ReactDOM.render (Provider , document.getElementById ( ' the root ' ));

  That ThreeButton.js you can get to the store, specifically how to get it to store it? First is the introduction of storeContext, and then in the class plus a static property contextType, it is assigned to storeContext, and components can be used to store the acquired this.context.

import React, { Component } from 'react';
import { storeContext } from './storeContext'; // 引入storeContext

export default class ThreeButton extends Component {
    static contextType = storeContext; // 加静态属性contextType, 赋值为storeContext
    
    componentDidMount() {
        let {store} = this.context; // this.context 获取到store
        console.log(store);
    }
    
    render() {
        return (
            <div style={{textAlign: "center"}}>
                <h1 id="counter">0</h1>
                <button type="button" className="btn btn-primary" style={{marginRight: '10px'}}>Add</button>
                <button type="button" className="btn btn-success" style={{marginRight: '10px'}}>Minus</button>
                <button type="button" className="btn btn-danger">Reset</button>
            </div>
        )
    }
}

  You can see the console print out of the store. Component finally get to the store, get it from the store in the state, injection components, it is necessary to declare a state allState components to receive store in the state, while in componentDidMounted time, call setState assigned to it

  static the contextType = storeContext; // add Static Property contextType, assigned storeContext 

    State = { 
        Allstate: {} 
    } 
    
    componentDidMount () { 
        the let {Store} = the this .context; // this.context acquired Store 
        the this .setState ({ 
            Allstate : store.getState () 
        }) 
    }
    

  The h1 from the state 0 to obtain

 <h1 id="counter">{this.state.allState.counter}</h1>

  Display page 5, there is no problem, suggesting that the state acquired from the store no problem. It would give the three button to add a click event, dispatch action to change the status, then add three functions. First introduced from redux.js three action, and then declare three functions dipatch action, the last is to click on the button to add the event.

import { add, minus, reset } from './redux';
.....

 add = () => {
        let {store} = this.context;
        store.dispatch(add);
    }
    
    minus = () => {
        let {store} = this.context;
        store.dispatch(minus);
    }
    
    reset = () => {
        let {store} = this.context;
        store.dispatch(reset);
    }

...
 <button type="button" className="btn btn-primary" style={{marginRight: '10px'}}
                    onClick={this.add}>Add</button>
                <button type="button" className="btn btn-success" style={{marginRight: '10px'}}
                    onClick={this.minus}>Minus</button>
                <button type="button" className="btn btn-danger"
                    onClick={this.reset}>Reset</button>

  Click the button, and state of the page does not refresh, that does not subscribe monitor state change or calling store.subscribe inside componentDidMounted page, it's callback function is also very simple, it is to get the state, calling setState ()

componentDidMount() {
        let {store} = this.context; // this.context 获取到store
        this.setState({
            allState: store.getState()
        })

        store.subscribe(() => {
            this.setState({
                allState: store.getState()
            })
        })
    }

  At this point, react and engage redux be successful. It follows the entire threeButton.js

import React, { Component } from 'react';
import { storeContext } from './storeContext'; // 引入storeContext
import { add, minus, reset } from './redux';

export default class ThreeButton extends Component {
    static contextType = storeContext; // 加静态属性contextType, 赋值为storeContext

    state = {
        allState: {}
    }
    
    componentDidMount() {
        let {store} = this.context; // this.context 获取到store
        this.setState({
            allState: store.getState()
        })

        store.subscribe(() => {
            this.setState({
                allState: store.getState()
            })
        })
    }
    
    add = () => {
        let {store} = this.context;
        store.dispatch(add);
    }
    
    minus = () => {
        let {store} = this.context;
        store.dispatch(minus);
    }
    
    reset = () => {
        let {store} = this.context;
        store.dispatch(reset);
    }
    render() {
        return (
            <div style={{textAlign: "center"}}>
                <h1 id="counter">{this.state.allState.counter}</h1>
                <button type="button" className="btn btn-primary" style={{marginRight: '10px'}}
                    onClick={this.add}>Add</button>
                <button type="button" className="btn btn-success" style={{marginRight: '10px'}}
                    onClick={this.minus}>Minus</button>
                <button type="button" className="btn btn-danger"
                    onClick={this.reset}>Reset</button>
            </div>
        )
    }
}

  Now recall the assembly to obtain store, dipatch aciton, and steps to achieve real-time listening, you will find that when we re-create another assembly time, it also has a lot of the same steps,

  1, add a static property contextType, so that we are able to acquire the entire assembly to the store, be sure the same

  2, add the state to accept the store in the state, certainly the same.

  3, access to state under componentDidMounted, monitor state, certainly the same

  4, dispatch action, this is hardly the same, because each component different action trigger

  5, render state, that is, the page ui, this is almost different.

  We can put this component is divided into three parts, the same section does not move, that different parts of how to deal with? For the different parts, are usually used function passed in different parts of the form by parameter passing, then write a function that returns this component. Since action and ui are two different types of things, can be divided into two different parameters, then this function is a function to accept a returning action, a returning accept a function ui assembly, a back assembly, this component contains the same section. Equivalent to

function connect(action) {
    return function(Componnet) {
        return class extends React.componnet {
            // 相同的部分
            render() {
                return <Componnet  {...this.state}></Componnet>
            }
        }
    }
}

  As long as this function is encapsulated, directly after calling this function, on the realization of the components automatically get to store, automatically monitor changes, as long as we write ui and action, then transfer into it. This function is actually a third-party components have a good package that react-redux library, which provides a connect method, look at its api, the most commonly used is the following way

connect(mapStateToProps, mapDispatchToProps)(MyComponent)。

  And write our own connect function uses the same method, but it is the first function may accept more arguments, mapStateToProps, the state transformed into props, because the components connect returned to the store can be acquired in the state, it should myComponnet state to pass, because myCompoent is responsible for rendering ui, for myComponnet, it is the props. the same also applies to mapDispatchToProps, the component is able to connect it to the store to obtain the dispatch, when passed to the myComponent , it becomes Props. look at how the use of these two parameters, they are first function, and then return the object. Why this design? Only function can be called, to be injected through the parameters and the state disptch, the object return, to facilitate merging object, all objects are combined, a myComponnet props to pass.

  For mapStateToProps, it takes a state as a parameter and returns an object that the property can be carried out using props in myComponet obtain and use, the value of it? That is, the parameters of state property, myComponent components use to which property in the state, which is read in state property as a parameter.

const mapStateToProps = state => ({
    counter: state.counter
})

  mapDispatchToProps, relatively little trouble, it accepts a dispatch as a parameter, the returned object properties can also be used props in myComponet carried obtain and use the value of it is a function, parameter can take may not accept the body of the function is dispatch action

const mapDispatchToProps = dispatch => ({
    add: () => dispatch({type: 'ADD'})
})

  React-Redux addition to connect function, but also provides a Provider components, and our custom storeContext.Provider consistent, but its use is directly attribute, the body of the component properties can be obtained quilt assembly. npm i react-redux --save rewritten using the react-redux assembly.

  StoreContext.js file is first removed, and then introduced from React-Redux Provider component in the index.js comprising App

import React from 'react';
import ReactDOM from 'react-dom';
import './index.css';
import App from './App';
import 'bootstrap/dist/css/bootstrap.css'; // 添加bootstrap 样式

import { store } from './redux'; // 引入 store
import { Provider } from 'react-redux';

//Sotre provided as shared data, App subassembly can be acquired and Store 
const ProviderWrapper = <Provider Store Store} = {> 
        <the App /> 
    </ Provider> 

ReactDOM.render (ProviderWrapper, document.getElementById ( ' the root ' )) ;

  ThreeButton.js will then divided into two parts, and a part of the first portion of the connect function connect (mapStateToProps, mapDispatchToProps), the main role is to store acquired, into props.

The other part is connect the second part of myComponent, which it is received props, rendering components. In a document can, in two files are no problem. We wrote in one file,

import React from 'react';
import { add, minus, reset } from './redux';
 import { connect } from 'react-redux';
// 纯渲染组件
function ThreeButton(props) {
   
    return (
        <div style={{textAlign: "center"}}>
            <h1 id="counter">{props.counter}</h1>
            <button type="button" className="btn btn-primary" style={{marginRight: '10px'}}
                onClick={props.add}>Add</button>
            <button type="button" className="btn btn-success"= {{marginRight style: ' 10px ' }} 
                the onClick = {} props.minus> Minus </ Button> 
            <Button type = " Button " className = " BTN-BTN Danger " 
                the onClick = {} props.reset> the Reset </ Button> 
        </ div> 
    ) 
} 

// to store in the state conversion of pure render component the props 
const mapStateToProps state = => ({ 
    counter: state.counter 
}) 

// Get the dispatch store, and action simultaneously engaged, the composition pure rendering component props, rendering assembly, the properties of an object called directly, you can dispatch action of 
const mapDispatchToProps = dispatch => ({
    the Add: () => dispatch (the Add), 
    minus: () => dispatch (minus), 
    RESET: () => dispatch (RESET) 
}) 

// Connect function they joined, ThreeButton use props can be used mapStateToProps and mapDispatchToProps returned object properties
 // and returns a component, the component can directly call the parent App.js the 
Export default Connect ( 
    mapStateToProps, 
    mapDispatchToProps, 
  ) (ThreeButton)

 

Guess you like

Origin www.cnblogs.com/SamWeb/p/11337197.html