react-redux的使用 2.react-redux的使用

npm install --save react-redux

react-redux的使用
2.react-redux的使用

1.基本使用

containers/Count.jsx
-- 容器组件 -- 用于传递 redux保存的状态和操作状态的方法 到 UI组件中

// 引入Count的UI组件
import CounUI from "../../components/Count";
import {
    createIncrementAction,
    createDecrementAction,
    createIncrementAsyncAction
} from "../../redux/count_action";


// 引入connect用于连接UI组件与redux
import {connect} from "react-redux";

// 1.mapStateToProps函数的返回的是一个对象,
// 2.返回的对象中的key就作为传递给UI组件props的key,value就作为传递给UI组件props的value--状态
// 3.mapStateToProps用于传递状态
// 4.容器连接UI组件时就已经把store的初始状态state传递给mapStateToProps函数
const mapStateToProps = (state) => {
    return {count: state}
}

// 1.mapDispatchToProps函数的返回的是一个对象,
// 2.返回的对象中的key就作为传递给UI组件props的key,value就作为传递给UI组件props的value--操作状态的方法
// 3.mapDispatchToProps用于传递操作状态的方法
// 4.容器连接UI组件时react-redux就已经把store的dispatch方法传递给mapDispatchToProps函数
const mapDispatchToProps = (dispatch) => {
    return {
        jia: number => dispatch(createIncrementAction(number)),
        jian: number => dispatch(createDecrementAction(number)),
        jiaAsync: (number,time) => dispatch(createIncrementAsyncAction(number, time)),

    }
}


// 使用connect()()创建并暴露一个Count容器组件
export default connect(mapStateToProps, mapDispatchToProps)(CounUI)


components/Count.jsx
-- UI组件 -- 通过this.props接收 redux保存的状态和操作状态的方法

import React, {Component} from 'react';


class CountUI extends Component {

    increment = () => {
        const {value} = this.selectNumber
		// 使用容器组件传递的方法
        this.props.jia(value*1)
    }
    decrement = () => {
        const {value} = this.selectNumber
        this.props.jian(value*1)
    }
    incrementOdd = () => {
        const {value} = this.selectNumber
		// 使用容器组件传递的状态
        if (this.props.count % 2 !== 0){
            this.props.jia(value*1)
        }
    }
    incrementAsync = () => {
        const {value} = this.selectNumber
        this.props.jiaAsync(value*1, 500)
    }

    render() {
        // console.log('UI组件接收到的props是:',this.props)
        return (
            <div>
                <h1>当前求和为: {this.props.count}</h1>
                <select ref={c => this.selectNumber = c}>
                    <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.incrementOdd}>当前求和为奇数加</button>
                <button onClick={this.incrementAsync}>异步加</button>
            </div>
        );
    }
}

export default CountUI;

2.优化

将UI组件写到容器组件下:

import React, {Component} from 'react';
// 引入connect用于连接UI组件与redux
import {connect} from "react-redux";
import {
    createIncrementAction,
    createDecrementAction,
    createIncrementAsyncAction
} from "../../redux/count_action";

// 定义UI组件
class Count extends Component {

    increment = () => {
        const {value} = this.selectNumber
        this.props.jia(value*1)
    }
    decrement = () => {
        const {value} = this.selectNumber
        this.props.jian(value*1)
    }
    incrementOdd = () => {
        const {value} = this.selectNumber
        if (this.props.count % 2 !== 0){
            this.props.jia(value*1)
        }
    }
    incrementAsync = () => {
        const {value} = this.selectNumber
        this.props.jiaAsync(value*1, 500)
    }

    render() {
        // console.log('UI组件接收到的props是:',this.props)
        return (
            <div>
                <h1>当前求和为: {this.props.count}</h1>
                <select ref={c => this.selectNumber = c}>
                    <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.incrementOdd}>当前求和为奇数加</button>
                <button onClick={this.incrementAsync}>异步加</button>
            </div>
        );
    }
}

// 映射状态
// const mapStateToProps = state => ({count: state})

// 映射操作状态的方法
// const mapDispatchToProps = dispatch => (
//     {
//         jia: number => dispatch(createIncrementAction(number)),
//         jian: number => dispatch(createDecrementAction(number)),
//         jiaAsync: (number,time) => dispatch(createIncrementAsyncAction(number, time)),
//     }
// )



// 使用connect()()创建并暴露一个Count容器组件
export default connect(
    state => ({count: state}),

    // mapDispatchToProps的一般写法
    // dispatch => ({
    //     jia: number => dispatch(createIncrementAction(number)),
    //     jian: number => dispatch(createDecrementAction(number)),
    //     jiaAsync: (number,time) => dispatch(createIncrementAsyncAction(number, time)),
    // })

    // mapDispatchToProps的简写方法
    // 简写不需要写dispatch,react-redux会自动分发
    {
        jia: createIncrementAction,
        jian: createDecrementAction,
        jiaAsync: createIncrementAsyncAction,
    }
    )(Count)


在index.js中:

import React from "react";
import ReactDOM from "react-dom";
import App from "./App";
import store from "./redux/store";
import {Provider} from "react-redux";


ReactDOM.render(
    // Provider专门为多个容器组件传递store,不用每个容器组件单独传store
    <Provider store={store}>
        <App />
    </Provider>,
    document.getElementById('root')
)

// 监测redux中状态的变化,只要redux中状态发生变化,就调用render重新渲染
// 使用react-redux就不需要再监测了,redux发生状态就会自动渲染
// store.subscribe(()=>{
//       ReactDOM.render(<App />, document.getElementById('root'))
// })

3.数据共享

多个容器组件之间数据的共享

由于是多个容器组件,那就存在多个不同的reducer,

// 引入 combineReducers,用于汇总多个reducer
import { combineReducers} from "redux";
// 引入为Count组件服务的reducer
import count from "./count";
// 引入为Person组件服务的reducer
import persons from "./person";

// combineReducers作用:汇总所有的reducer变成一个总得reducer
const allReducer = combineReducers({
    count,
    persons,
})        

export default allReducer

在store.js中使用allReducer

export default createStore(allReducer, composeWithDevTools(applyMiddleware(thunk)))

Count.jsx

import React, {Component} from 'react';
// 引入connect用于连接UI组件与redux
import {connect} from "react-redux";
import {
    increment,
    decrement,
    incrementAsync
} from "../../redux/actions/count";

// 定义UI组件
class Count extends Component {

    increment = () => {
        const {value} = this.selectNumber
        this.props.increment(value * 1)
    }
    decrement = () => {
        const {value} = this.selectNumber
        this.props.decrement(value * 1)
    }
    incrementOdd = () => {
        const {value} = this.selectNumber
        if (this.props.count % 2 !== 0) {
            this.props.increment(value * 1)
        }
    }
    incrementAsync = () => {
        const {value} = this.selectNumber
        this.props.incrementAsync(value * 1, 500)
    }

    render() {
        // console.log('UI组件接收到的props是:',this.props)
        return (
            <div>
                <h2>我是Count组件</h2>
                <h4>下方人总数为:{this.props.personsCount}</h4>
                <h1>当前求和为: {this.props.count}</h1>
                <select ref={c => this.selectNumber = c}>
                    <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.incrementOdd}>当前求和为奇数加</button>
                <button onClick={this.incrementAsync}>异步加</button>
            </div>
        );
    }
}


// 使用connect()()创建并暴露一个Count容器组件
// 由于用了合并reducer方法,所以state变成了一个对象
export default connect(
    state => ({
        count: state.count,
        personsCount:state.persons.length}), // 在Count中使用Person的数据
    {
        increment,
        decrement,
        incrementAsync,
    }
)(Count)

Person.jsx

import React, {Component} from 'react';
import {nanoid} from "nanoid";
import {connect} from "react-redux";
import {addPerson} from '../../redux/actions/person'


class Person extends Component {

    addPerson = () => {
        const name = this.nameNode.value
        const age = this.ageNode.value
        const personObj = {id:nanoid(),name,age}
        this.props.addPerson(personObj)
        this.nameNode.value = ''
        this.ageNode.value = ''
        
    }

    render() {
        return (
            <div>
                <h2>我是Person组件</h2>
                 <h4>上方求和为{this.props.count}</h4>
                <input ref={c=>this.nameNode = c} type="text" placeholder='输入名字'/>
                <input ref={c=>this.ageNode = c} type="text" placeholder='输入年龄'/>
                <button onClick={this.addPerson}> ADD</button>
                <ul>
                    {
                        this.props.persons.map(ren=>{
                            return (
                                <li key={ren.id}>
                                    {ren.name}---{ren.age}
                                </li>
                            )
                        })
                    }
                </ul>
            </div>
        );
    }
}

export default connect(
    state=>({
        persons:state.persons,
        count:state.count}),  // 在Person中使用Count的数据
    {addPerson}
)(Person);