react状态管理方法总结

时间:2021-1-8 作者:admin

class组件中使用context

1、创建context上下文

// utils.js
import React, {createContext} from 'react'
const MoneyContext = createContext()  // 创建上下文
export default MoneyContext  // 导出MoneyContext

2、父组件

import React, { Component } from 'react';
import Child from './child'
import MoneyContext from '../utils/Context'

export default class Parent extends Component {
    // 设置一个money的初始状态
    state ={ 
        money: 100
    }
    // 定义修改自身状态的方法
    setMoney = (newMoney)=>{
        this.setState({
            money: newMoney
        })
    }
    render() {
        return (
            <MoneyContext.Provider value={{money: this.state.money, setMoney:this.setMoney}}>
                <div>
                    <h3>父组件 ---- parent</h3>
                    <Child></Child>
                </div>
            </MoneyContext.Provider>

        )
    }
}

在父组件中:使用MoneyContext.Provider将父组件包裹,同时添加value属性,将状态和方法传递给子孙组件调用。

3、子组件

import React, { Component } from 'react';
import GrandChild from './grandChild'
import MoneyContext from '../utils/Context'

export default class Child extends Component {
    static contextType = MoneyContext
    // 通过这种方法接收父组件传递的属性,可以在其他生命周期中使用

    constructor(props, context) {
        console.log('11',context);
        super()
        this.state = {
            money1: context.money
        }
    }+
    componentDidMount() {
        console.log(this.context.money)
        /* 在组件挂载完成后,使用 MyContext 组件的值来执行一些有副作用的操作 */
    }

    componentDidUpdate(props, context){
        console.log(this.context);

    }
    componentWillUnmount() {
        let value = this.context;
    }
    render() {
        return (
            <div>
                <h3>子组件 ----- child</h3>
                <p>父组件传递的值 ----{this.context.money}</p>
                <GrandChild></GrandChild>
            </div>
        )
    }
}

使用static contextType = MoneyContext,接收父组件传递过来的value,可以在其他的生命周期函数中来执行一些有副作用的操作。
挂载在 class 上的 contextType 属性会被重赋值为一个由 React.createContext() 创建的 Context 对象。这能让你使用 this.context 来消费最近 Context 上的那个值。你可以在任何生命周期中访问到它,包括 render 函数中。

4、孙子组件

import React, { Component } from 'react';
import MoneyContext from '../utils/Context'

export default class GrandChild extends Component {

    render() {
        return (
            // 只能在render函数中使用,不能在其他生命周期数中使用
            <MoneyContext.Consumer>
                        {
                            value => {
                                return (
                                    <div>
                                        <h3>孙子组件 ---- grandChild</h3>
                                        <p>父组件传递的值 ---- {value.money}</p>
                                        <button onClick={() => value.setMoney(200)}>钱不够</button>
                                    </div>

                                )
                            }
                        }
            </MoneyContext.Consumer>
        )
    }
}

使用MoneyContext.Consumer标签将组件包裹,并且内部通过函数的形式来获取父组件传递的状态和方法。
因为这种使用Consumer的形式来订阅context,只能在render中访问父组件传递的方法和状态。所以,最好使用函数组件的方式来订阅context。引用官网上的说法就是:

一个 React 组件可以订阅 context 的变更,这让你在函数式组件中可以订阅 context。

这种方法需要一个函数作为子元素(function as a child)。这个函数接收当前的 context 值,并返回一个 React 节点。
传递给函数的 value 值等价于组件树上方离这个 context 最近的 Provider 提供的 value 值。
如果没有对应的 Provider,value 参数等同于传递给 createContext() 的 defaultValue。

在函数组件中使用context、useState

在函数组件中使用context和在类组件中使用context的方法基本一致

1、创建context上下文

// utils.js
import React, {createContext} from 'react'
const MoneyContext = createContext()  // 创建上下文
export default MoneyContext  // 导出MoneyContext

2、父组件

import React, { useState } from 'react';
import Child from './child'
import MoneyContext from '../utils/Context'

const Parent = () => {
    // 使用useState创建money状态,并初始化
    let [money, setMoney] = useState(10)
    return (
        <MoneyContext.Provider value={{money: money}}>
            <div>
                <h3>函数组件父组件</h3>
                <button onClick={() => setMoney(money=100)}>修改money</button>
                <hr/>
                <Child></Child>
            </div>
        </MoneyContext.Provider>
    );
}

export default Parent;

3、子组件

import React from 'react';
import GrandChild from './grandChild'
import MoneyContext from '../utils/Context'

function Child() {
    return (
        <MoneyContext.Consumer>
            { 
                value => {
                    return (                
                        <div>
                            <h3>函数组件子组件</h3>
                             <p>父组件传递的值---money:{value[0]}----age:{value[1]}</p>
                            <hr/>
                            <GrandChild></GrandChild>
                        </div>
                    )
                }
            }
        </MoneyContext.Consumer>
    )
}

export default Child

4、孙子组件

import React from 'react';
import MoneyContext from '../utils/Context'

const GrandChild = () => {
    return (
        <div>
            <h3>函数组件孙子组件</h3>
        </div>
    );
}

export default GrandChild;

函数组件使用context、useContext、useReducer进行状态管理

1、创建context上下文

import React, {createContext} from 'react'
const MoneyContext = createContext()
export default MoneyContext

2、创建reducer

//处理money的reducer
const moneyReducer = (state, action) => {
    switch (action.type) {
        case 'ADD':
            return state + 10;
        case 'SUB':
            return state - 10;
        default:
            return state;
    }
}
// 处理age的reducer
const ageReducer = (state, action) => {
    switch (action.type) {
        case 'ADD':
            return state + 1;
        case 'SUB':
            return state - 1;
        default:
            return state;
    }
}
export {
    moneyReducer,
    ageReducer
}

3、父组件

import React, { useReducer } from 'react';
import Child from './child'
import MoneyContext from '../utils/Context'

import { moneyReducer, ageReducer } from './reducer'

const Parent = () => {
    // 初始化money状态,并指定对应的reducer处理函数,最后返回触发对应reducer函数的dispatch
    let [money, moneyDispatch] = useReducer(moneyReducer, 10)
    let [age, ageDispatch] = useReducer(ageReducer, 15)
    return (
        <MoneyContext.Provider value={[money, age, moneyDispatch, ageDispatch]}>
            <div>
                <h3>函数组件父组件</h3>
                <button onClick={() => moneyDispatch({type: 'ADD'})}>修改money</button>
                <hr/>
                <Child></Child>
            </div>
        </MoneyContext.Provider>  

    );
}

export default Parent;

useReducer

useReducer接收两个参数:

第一个参数是:reducer函数,第二个参数是:初始化的state。
返回值是最新的state和dispatch函数(用来发送action触发reducer函数,计算对应的state)。

按照官网的说法:

在某些场景下,useReducer 会比 useState 更适用,例如 state 逻辑较复杂且包含多个子值,
或者下一个 state 依赖于之前的 state 等。
并且,使用 useReducer 还能给那些会触发深更新的组件做性能优化,
因为你可以向子组件传递 dispatch 而不是回调函数 。

4、子组件

import React from 'react';
import GrandChild from './grandChild'
import MoneyContext from '../utils/Context'

function Child() {
    return (
        <MoneyContext.Consumer>
            { 
                value => {
                    return (                
                        <div>
                            <h3>函数组件子组件</h3>
                             <p>父组件传递的值---money:{value[0]}----age:{value[1]}</p>
                             // 调用父组件传递的moneyDispatch,将money的值减少
                             <button onClick={() => {value[2]({type:"SUB"})}}>子组件中修改money</button>
                            <hr/>
                            <GrandChild></GrandChild>
                        </div>
                    )
                }
            }
        </MoneyContext.Consumer>
    )
}

export default Child

接收父组件传递的状态和方法–方法一

使用MoneyContext.Consumer标签,内部通过函数的形式接收父组件传递的状态(money…)和方法(moneyDispatch)

5、孙子组件

import React, { useContext } from 'react';
import MoneyContext from '../utils/Context'

const GrandChild = () => {
    const [money,age, moneyDispatch,ageDispatch] = useContext(MoneyContext);

    return (
        <div>
            <h3>函数组件孙子组件</h3>
            <p>父组件传递的值 --- {money} --- {age}</p>
            // 调用ageDispatch方法触发对应的reducer使age++
            <button onClick={() => ageDispatch({type: 'ADD'})}>孙子长大了</button>
        </div>
    );
}

export default GrandChild;

接收父组件传递的状态和方法–方法二

通过使用useContext来读取context的值以及订阅context的变化。

useContext()接收一个context对象(React.createContext的返回值)并返回该context的当前值。当前的context值由上层组件中距离当前组件最近的<MoneyContext.Provider>中的value决定。当上层最近的<MoneyContext.Provider>更新时,该Hook会触发重新渲染,并使用最新的context value值。即使祖先使用了React.memo或者shouldComponentUpdate,也会重新渲染。

提示

useContext(MyContext)相当于class组件中的static contextType = MyConntext 或者<MyContext.Comsumer>

redux状态管理-todoList案例

1、action

// action/index.js
import store from '../store'

const ADD_TODO_ITEM = "ADD_TODO_ITEM"
const UPDATE_CHECKED = 'UPDATE_CHECKED'
const DELETE_USER = 'DELETE_USER'
const action = {
    addItem : (userInfo) => {
        const action =  {
            type: ADD_TODO_ITEM,
            userInfo
        }
        store.dispatch(action)
    },
    updatedChecked: (id) => {
        const action = {
            type: UPDATE_CHECKED,
            id
        }
        store.dispatch(action)
    },
    deleteUser: (id) => {
        const action = {
            type: DELETE_USER,
            id
        }
        store.dispatch(action)
    }
}

export default action

创建action对象,并通过store提供的dispatch方法,发送action。将其封装成函数以便组件直接调用(action.addItem()等)。

2、reducer

// reducer/index.js
const toDoList = [
    {id: 1, username: '朱元璋 ', position: '明太祖', isChecked: true},
    {id: 2, username: '朱允炆', position: '建文帝', isChecked: false},
]
const reducer = (state = toDoList, action) => {
    switch (action.type) {
        case 'ADD_TODO_ITEM':
            return handler.addItem(state,action.userInfo)
        case 'UPDATE_CHECKED':
            return handler.updateChecked(state, action.id)
        case 'DELETE_USER':
            return handler.deleteUser(state, action.id)

        default:
            return state
    }
}

const handler = {
    addItem: (arr,userInfo) => {
        const newArr = arr.slice()
        userInfo = Object.assign(userInfo, {id: arr.length + 1})
        newArr.push(userInfo)
        return newArr
    },
    updateChecked: (arr, id) => {
        const newArr = arr.slice()
        // 拷贝一个新数组,赋值给newArr,来操作新的数组。
        // 防止如果在arr数组中存在一个其他数组,操作其他数组时state虽然会发生改变,但不会引起arr数组地址的改变。这种情况在react-redux中:react-redux内部会认为arr的地址没有发生改变,从而不会重新渲染组件(把它当作state没有发生改变处理)。
        for(let i=0;i<newArr.length;i++){
            if(newArr[i].id === id){
                newArr[i].isChecked = !newArr[i].isChecked
            }
        }
        return newArr
    },
    deleteUser: (arr, id) => {
        return arr.filter(item => {
            return item.id === id ? false : true
        })
    }
}

export default reducer

reducer()是一个函数接收两个参数:一个是之前的state,一个是action。函数体内部通过判断,action.type的值,来分别执行不同的操作。

3、store

// store/index.js
import { createStore } from 'redux'
import reducer from '../reducer'
const store = createStore(reducer)
export default store

创建store仓库,并指定对应的处理函数reducer()

4、Home组件

// pages/Home.jsx
import React, { Component } from 'react';
import List from '../components/List'
import action from '../action/index'
export default class Home extends Component {
    state = {
        userInfo: {
            username: '',
            position:'',
        }
    }
    getUserInfo = (e) => {
        // 收集输入框中的值
        let userInfo = Object.assign(this.state.userInfo, {[e.target.id]: e.target.value})
        this.setState({
            userInfo
        })
    }

    submit = () => {
        // 调用函数发送action,添加用户
        action.addItem(this.state.userInfo)
        this.setState({  // 清空输入框
            userInfo: {
                username: '',
                position:'',
            }
        })
    }
    render() {
        return (
            <div>
                username: <input type="text" id="username" value={this.state.userInfo.username} onChange={this.getUserInfo}/> 
                position: <input type="text" id="position" value={this.state.userInfo.position} onChange={this.getUserInfo}/>
                <button onClick={this.submit}>提交</button>
                <List></List>  // 调用List组件,渲染列表
            </div>
        )
    }
}

5、List组件

// components/List.jsx

import React, { Component, useState } from 'react';
import store from '../store'
import action from '../action'

// 定义一个函数组件,用来生成列表中的每一项 li标签
const Item = (props) => {
    const [liStyle, setLiStyle] = useState({
        color: 'springgreen',
    })
    // 修改复选框的状态,修改当前用户的isChecked属性
    const updatedChecked = (e) => {
        action.updatedChecked(e.target.parentNode.id*1)
    }
    // 调用删除用户的函数
    const deleteUser = (e) => {
        action.deleteUser(e.target.parentNode.id*1)
    }
    return <li style={props.item.isChecked ? liStyle : {}}  id={props.item.id}>
             <input type="checkbox" checked={props.item.isChecked} onChange={updatedChecked}/>
             {props.item.username} ---- {props.item.position} 
             <button onClick={deleteUser}>删除用户</button>
          </li>
}

export default class List extends Component {

    componentDidMount() {
        // 调用store.subscribe()方法,监听reducer函数中state的改变
        store.subscribe(() => {
            // const updatedData = store.getState()
            this.setState({})  // 通过一个设置空对象,来促使组件重新渲染
        })
    }
    render() {
        return (
            <div>
                <ul>
                    {
                        store.getState().map((item) => {
                        return <Item item={item} key={item.id}/>
                        })
                    }
                </ul>
            </div>
        )
    }
}

react-redux状态管理-todoList案例

React-Redux 将所有的组件分成两部分:UI组件(presentational component)和容器组件(container component)。

UI组件(用户自定义组件)的特征:

  • 只负责UI的呈现,不带有任何的业务逻辑
  • 没有状态(即不使用this.state这个变量)
  • 所有数据都由参数(this.props)提供
  • 不使用Redux的API

因为不含状态,所以UI组件又被称为”纯组件”,即像纯函数一样,纯粹由参数决定它的值。
容器组件(调用connect()函数生成的组件)的特征:

  • 负责管理数据和业务逻辑,不负责UI的呈现
  • 带有内部状态
  • 使用Redux的API

如果一个组件中既有UI又有业务逻辑,将它拆分成两部分:外面是一个容器组件,里面包一个UI组件。前者负责与外部的通信,将数据传递给后者,由后者负责渲染出视图。

pages

pages/todoList/Home.jsx

// pages/todoList/Home.jsx

import React, { Component } from 'react';
import List from '../../components/List'
import action from './toDoListAction'
import { connect } from 'react-redux'

class Home extends Component {
    state = {
        userInfo: {
            username: '',
            position:'',
        }
    }
    getUserInfo = (e) => {
        let userInfo = Object.assign(this.state.userInfo, {[e.target.id]: e.target.value})
        this.setState({
            userInfo
        })
    }

    submit = () => {
        this.props.addItem(this.state.userInfo)
        this.setState({
            userInfo: {
                username: '',
                position:'',
            }
        })
    }
    render() {
        return (
            <div>
                username: <input type="text" id="username" value={this.state.userInfo.username} onChange={this.getUserInfo}/> 
                position: <input type="text" id="position" value={this.state.userInfo.position} onChange={this.getUserInfo}/>
                <button onClick={this.submit}>提交</button>
                <List></List>
            </div>
        )
    }
}

// 不需要接收状态,将action对象展开,获取action中定义的方法
export default connect(null, {...action})(Home)

Home就是UI组件,通过connect()(Home)生成的就是容器组件。

pages/todoList/toDoListAction.js—定义action的文件

const ADD_TODO_ITEM = "ADD_TODO_ITEM"
const UPDATE_CHECKED = 'UPDATE_CHECKED'
const DELETE_USER = 'DELETE_USER'
const action = {
    addItem : (userInfo) => {
        const sendAction =  {
            type: ADD_TODO_ITEM,
            userInfo
        }
        return sendAction
    },
    updatedChecked: (id) => {
        const action = {
            type: UPDATE_CHECKED,
            id
        }
        return action
    },
    deleteUser: (id) => {
        const action = {
            type: DELETE_USER,
            id
        }
        return action
    }
}

export default action

pages/todoList/toDoListReducer.js—用来处理当前组件的reducer函数

const toDoList = [
    {id: 1, username: '朱元璋 ', position: '明太祖', isChecked: true},
    {id: 2, username: '朱允炆', position: '建文帝', isChecked: false},
]
const reducer = (state = toDoList, action) => {

    switch (action.type) {
        case 'ADD_TODO_ITEM':
            return handler.addItem(state,action.userInfo)
        case 'UPDATE_CHECKED':
            return handler.updateChecked(state, action.id)
        case 'DELETE_USER':
            return handler.deleteUser(state, action.id)

        default:
            return state
    }
}

const handler = {
    addItem: (arr,userInfo) => {
        const newArr = JSON.parse(JSON.stringify(arr))
        // react-redux内部通过判断一个组件中接收到的state(connect(mapStateToprops)函数中的state值)的地址是否发生改变来确定组件是否重新渲染。
        // 防止操作原数组中的内容时,而原数组的地址没有发生改变,而无法促使组件重新渲染的情况。因此,重新拷贝一份新的数组,以区别原来的数组。
        userInfo = Object.assign(userInfo, {id: arr.length + 1})
        newArr.push(userInfo)
        return newArr
    },
    updateChecked: (arr, id) => {
        const newArr = arr.slice()
        for(let i=0;i<newArr.length;i++){
            if(newArr[i].id === id){
                newArr[i].isChecked = !newArr[i].isChecked
            }
        }
        return newArr
    },
    deleteUser: (arr, id) => {
        return arr.filter(item => {
            return item.id === id ? false : true
        })
    }
}

export default reducer

components–子组件

components/List.jsx

import React, { Component, useState } from 'react';
import action from '../pages/todoList/toDoListAction'
import { connect } from 'react-redux'


const Item = (props) => {
    const [liStyle] = useState({
        color: 'springgreen',
    })
    // 修改复选框的选中状态
    const updatedChecked = () => props.updatedChecked(props.item.id)
    // 删除当前用户
    const deleteUser = () => props.deleteUser(props.item.id)

    return <li style={props.item.isChecked ? liStyle : {}}  id={props.item.id}>
              <input type="checkbox" checked={props.item.isChecked || ''} onChange={updatedChecked}/>
              {props.item.username} ---- {props.item.position} 
              <button onClick={deleteUser}>删除用户</button>
           </li>
}

 class List extends Component {

    render() {
        console.log(this.props);
        return (
            <div>
                <ul>
                    {

                        this.props.todoList.map((item) => {
                        return <Item item={item} key={item.id} {...this.props}/>
                        })
                    }
                </ul>
            </div>
        )
    }
}

/* const mapStateToProps = (state) => {
     return {
         todoList: state.toDoListReducer
     }
 }
 const mapDispatchToProps = (dispatch) => {
     return {
         updatedChecked: (id) => {
             dispatch(action.updatedChecked(id))
         },
         deleteUser: (id) => dispatch(action.deleteUser(id))
     }
 }
export default connect(mapStateToProps, mapDispatchToProps)(List)
*/

// 上面的代码可以简写为:
export default connect(state => ({ todoList: state.toDoListReducer }), { ...action })(List)

export default connect(mapStateToProps, mapDispatchToProps)(List)connect()接收两个参数:

mapStateToPropsmapDispatchToProps

前者负责输入逻辑,即将state映射到UI组件的参数(props)。mapStateToProps是一个函数,它接收一个state作为参数,返回一个对象。里面的每一个键值对就是一个映射。mapStateToProps会订阅Store,每当state更新的时候,就会自动执行,重新计算UI组件的参数,从而触发UI组件的重新渲染。

后者负责输出逻辑,即将用户对UI组件的操作映射成Action。用来建立UI组件的参数到store.dispatch方法的映射。也就是说它定义了用户的哪些操作应当当作action,传给store。它既可以是一个函数,也可以是一个对象。

reducer—合并私有reducer

reducer/index.js

import {combineReducers} from 'redux'
import toDoListReducer from '../pages/todoList/toDoListReducer'

// 通过调用combineReducers方法来合并,每个组件定义的私有reducer
export default combineReducers({
    toDoListReducer
})

store—创建store仓库

store/index.js

import { createStore } from 'redux'
import reducer from '../reducer'

const store = createStore(reducer)

export default store

app组件

import React from 'react'
import { Provider } from 'react-redux'
import store from './05-communication-react-redux/store'

import Home from './05-communication-react-redux/pages/todoList/Home'

function App() {
  return (
    <Provider store={store}>
      <div className="App">
        <Home></Home>
      </div>
    </Provider>

  );
}

export default App;

使用Provider在根组件外面包了一层,这样App的所有子组件就默认都可以拿到state了。
它的原理是:React组件的context属性

函数组件状态管理—react-redux

在函数组件中使用react-redux提供的 useSelectoruseDispatch,进行状态管理。

pages

// pages/todoList/Home.jsx
import React, { useState, useEffect } from 'react';
import List from '../../components/List'
import action from './toDoListAction'
import { useDispatch } from 'react-redux'
export default () => {

    let [userInfo, setUserInfo] = useState({
        username: '',
        position:'',
    });

    const dispatch = useDispatch()
    const getUserInfo = (e) => {
        let currentUserInfo = Object.assign(userInfo, {[e.target.id]: e.target.value})
        const current = JSON.parse(JSON.stringify(currentUserInfo))
        // currentUserInfo是在原对象上进行更改,修改之后userInfo的地址没有发生改变,所以不会触发组件的更新,所以可以拷贝一份current,赋值给userInfo来触发组件的更新。 
        setUserInfo(current)
    }

    const submit = () => {
        dispatch(action.addItem(userInfo))
        setUserInfo({
            username: '',
            position:'',
        })
    }


    return (
        <div>
            username: <input type="text" id="username" value={userInfo.username} onChange={getUserInfo}/> 
            position: <input type="text" id="position" value={userInfo.position} onChange={getUserInfo}/>
            <button onClick={submit}>提交</button>
            <List></List>
        </div>
    )

}


// pages/todoList/toDoListAction.js

const ADD_TODO_ITEM = "ADD_TODO_ITEM"
const UPDATE_CHECKED = 'UPDATE_CHECKED'
const DELETE_USER = 'DELETE_USER'
const action = {
    addItem : (userInfo) => {
        const sendAction =  {
            type: ADD_TODO_ITEM,
            userInfo
        }
        return sendAction
    },
    updatedChecked: (id) => {
        const action = {
            type: UPDATE_CHECKED,
            id
        }
        return action
    },
    deleteUser: (id) => {
        const action = {
            type: DELETE_USER,
            id
        }
        return action
    }
}

export default action
// pages/toDoListReducer.js

const toDoList = [
    {id: 1, username: '朱元璋 ', position: '明太祖', isChecked: true},
    {id: 2, username: '朱允炆', position: '建文帝', isChecked: false},
]
const reducer = (state = toDoList, action) => {
    switch (action.type) {
        case 'ADD_TODO_ITEM':
            return handler.addItem(state,action.userInfo)
        case 'UPDATE_CHECKED':
            // console.log(handler.updateChecked(newState, action.id))
            return handler.updateChecked(state, action.id)
        case 'DELETE_USER':
            return handler.deleteUser(state, action.id)

        default:
            return state
    }
}

const handler = {
    addItem: (arr,userInfo) => {
        // 这里直接使用arr原数组,也没有问题。不知道为什么在class组件中不行
        const newArr = JSON.parse(JSON.stringify(arr))
        userInfo = Object.assign(userInfo, {id: arr.length + 1})
        newArr.push(userInfo)
        return newArr
    },
    updateChecked: (arr, id) => {
        const newArr = arr.slice()
        for(let i=0;i<newArr.length;i++){
            if(newArr[i].id === id){
                newArr[i].isChecked = !newArr[i].isChecked
            }
        }
        return newArr
    },
    deleteUser: (arr, id) => {
        return arr.filter(item => {
            return item.id === id ? false : true
        })
    }
}

export default reducer

components

// components/List.jsx
import React, { useState } from 'react';
import action from '../pages/todoList/toDoListAction'
import { useSelector, useDispatch } from 'react-redux'


const Item = (props) => {
    const [liStyle] = useState({
        color: 'springgreen',
    })
    const dispatch = useDispatch()

    const updatedChecked = () => dispatch(action.updatedChecked(props.item.id))

    const deleteUser = () => dispatch(action.deleteUser(props.item.id))

    return <li style={props.item.isChecked ? liStyle : {}}  id={props.item.id}><input type="checkbox" checked={props.item.isChecked || ''} onChange={updatedChecked}/> {props.item.username} ---- {props.item.position} <button onClick={deleteUser}>删除用户</button></li>
}


export default () => {
    const todoList = useSelector(state => state.toDoListReducer)
    return (
        <div>
            <ul>
                {

                    todoList.map((item) => {
                    return <Item item={item} key={item.id} />
                    })
                }
            </ul>
        </div>
    )

}

reducer—合并reducer

// reducer/index.js

import {combineReducers} from 'redux'
import toDoListReducer from '../pages/todoList/toDoListReducer'
import calculatorReducer from '../pages/calculator/calculatorReducer'


export default combineReducers({
    toDoListReducer,
    calculatorReducer
})

store—创建store

// store/index.js
import { createStore } from 'redux'
import reducer from '../reducer'

const store = createStore(reducer)

export default store

App.js

import React from 'react'
import { Provider } from 'react-redux'
import store from './05-communication-react-redux/store'

import Home from './06-communication-react-redux-hooks/pages/todoList/Home'

function App() {
  return (
    <Provider store={store}>
      <div className="App">
        <Home></Home>
      </div>
    </Provider>

  );
}

export default App;

声明:本文内容由互联网用户自发贡献自行上传,本网站不拥有所有权,未作人工编辑处理,也不承担相关法律责任。如果您发现有涉嫌版权的内容,欢迎进行举报,并提供相关证据,工作人员会在5个工作日内联系你,一经查实,本站将立刻删除涉嫌侵权内容。