redeux+react-redux配合使用

189 阅读5分钟

redux是属于js的状态管理模式,我们可以借助react-redux连接上redux和react-redux

我们要引起一个组件更新有两种方案

  1. 修改组建的state数据

  2. 修改组件的props

所以我们react-redux其实做了这样一件事情

把redux的state映射到组件的props,这样修改redux的state,就会触发组件的props的改变,组件就会更新。这样就只会更新使用到了redux的组件

npm i redux --save
npm i react-redux -S

1.1 创建状态管理器

第一步,我们先创建一个redux状态管理器

import { legacy_createStore as createStore, applyMiddleware } from "redux"function reducer (state = {    //初始数据,初始数据作为第一个参数的默认值    msg: "hello",    count: 0}, action) {    //这里写修改state的行为    //action一定要有type    switch (action.type) {        case "changeMes":            //可以叫其他名字,只不过最好叫payload            state.mes = action.payload;            //return的值会直接作为state的新值            //一定要再修改完后,返回state            //如果配合上react-redux,就必须返回的时候,解除引用            return { ...state }        case "addCount":            state.count += 1;            return { ...state }        default:            return state;    }}let store = createStore(    reducer);export default store;

1.2 使用react-redux

第一步,用react-redux提供的Provider组件包裹App

我们用Provider包裹了App,就等于接管了项目

import React from 'react';import ReactDOM from 'react-dom/client';import './index.css';import App from './App';import reportWebVitals from './reportWebVitals';import store from "./store"// 1.js引入provide组件,// 因为我们试图把state映射到props,所以我们要成为所有的组件父组件import { Provider } from 'react-redux';const root = ReactDOM.createRoot(document.getElementById('root'));root.render(  <React.StrictMode>    {/* 2.用Provider把项目包起来,并且加上一个store属性,给入创建redux对象*/}    <Provider store={store}>      <App />    </Provider>  </React.StrictMode>);//这样子做不好,他会导致整个 项目都刷新。等同于按F5刷新了页面// store.subscribe(() => {//     root.render(//         <React.StrictMode>//             <App />//         </React.StrictMode>//     );// })// If you want to start measuring performance in your app, pass a function// to log results (for example: reportWebVitals(console.log))// or send to an analytics endpoint. Learn more: https://bit.ly/CRA-vitalsreportWebVitals();

第二步-使用connect把redux的state映射到组建的props

业务逻辑写到容器组件中

import store from "./store"import { connect } from "react-redux"function ReduxCom (props) {    console.log(props);    return <div>        <div>            mes:{props.msg}        </div>        <div>            count: {props.count}        </div>        <button onClick={() => {            props.dispatch({                type: "changeMes",                payload: "hello world"            })        }}>修改redux的mes</button>        <button onClick={() => {            props.dispatch({                type: "addCount",                payload: "hello world"            })        }}>count+1</button>    </div>}function mapStateToProps (state) {    console.log(state);    //state就是redux的state    //return的这个对象将会合并到组建的props里    return {        mes: state.msg,        count: state.count,    }}export default connect(mapStateToProps)(ReduxCom);

这样指定的state都映射到props里了

思考:为什么要指定state映射,而不是直接全部映射

因为props的改变会导致组件更新,如果全部映射,那么有的redux中的state数据不是这个组件用的,它的更新也会引起组件更新,所以我们要指定映射组件用到的state,而不是直接全面映射。

第三步,为了让调用更加方便

我们可以把对某个数据的修改写成方法,然后映射到props中,我们可以不映射action,但是为了让调用方便,我们可以映射下

//redux现在和react每有任何关联// redux是属于js的状态管理模式,// 我们可以借助react-redux连接上redux和react-reduximport { connect } from "react-redux"//把redux创建的state全部映射为props-》修改state-》等同于修改了props-》触发了组件更新//哪个组件要使用状态管理//比如我们要再这个组件使用状态管理,我们就在这里引入connectfunction ReduxCom (props){    console.log(props);    return (        <div>            {props.msg}            <button onClick={()=>{{props.changeMsg()}}}>修改redux的msg</button>        </div>    )}//  connect调用后,会返回一个高阶组件,所以我们先调用connect,然后把该组件给到高阶组件//  第一个参数,对于state的映射关系//          必须传递第一个参数,不传第一个,就不会把state映射为props,//          那么修改不会触发更新function mapState (state) {    return {        msg: state.msg    }}//第二个参数function mapAction(dispatch){    return {        changeMsg(){            dispatch({                type:'changeMsg',                payload:'hello world!'            })        }    }}export default connect(mapState,mapAction)(ReduxCom) 

2.1 redux+react-redux分模块使用

 如果项目很大,或者项目划分比较明确,需要将状态管理器也分模块去处理

假设我们有两个模块,我们写成reducer和reducer2

步骤

  1. 创建不同模块的reducer方法

  2. 引入combineReducers方法,把不同模块的reducer何在一个对象里给入方法

  3. 把combineReducers返回的对象给到createStore

    //1,引入redux的applyMiddleWareimport { legacy_createStore as createStore ,combineReducers} from "redux";function reducer(state = { // 初始化数据,初始数据作为第一个参数的默认值 msg: 'hello', count: 0}, action) { // 这里写修改state的行为 // action一定要有type switch (action.type) { case 'changeMsg': // 可以叫其他名字,只不过最好叫payload state.msg = action.payload // return的值会直接作为state的新值 // 一定要修改完后,再返回state return { ...state }; case 'addCount': state.count += 1 return { ...state }; default: return { ...state }; }}function reducer2(state = { arr:[]}, action) { switch (action.type) { case 'pushArr': // 对于state里面的数组,对象,我们也得解除引用 let _arr=[...state.arr]; _arr.push(action.payload); return {...state,arr:_arr}; case 'replaceArr': //这里写不了异步操作 state.arr = action.payload; return { ...state }; default: return state ; }}//给入一个对象,对象里面写入我们的模块//然后得到一个合并的reducerlet combineReducer=combineReducers({reducer,reducer2})let store=createStore(combineReducer)export default store

然后我们state就会分开模块,**注意使用的时候要拿出具体模块**

import store from "./store"import { connect } from "react-redux"function ReduxCom (props) {    console.log(props);    return <div>        <div>            mes:{props.msg}        </div>        <div>            count: {props.count}        </div>        <button onClick={() => {            props.changeMes()        }}>修改redux的mes</button>        <button onClick={() => {            props.addCount();        }}>count+1</button>    </div>}function mapStateToProps (state) {    console.log(state);    return {        //因为分了模块,所以取出得先取处模块,再取模块得数据        mes: state.reducer.msg,        count: state.reducer.count,        arr: state.reducer2.arr    }}function mapActions (dispatch) {    return {        changeMes () {            dispatch({                type: "changeMes",                payload: "hello world"            })        },        addCount () {            dispatch({                type: "addCount"            })        }    }}export default connect(mapStateToProps, mapActions)(ReduxCom);

我们可以看到我们从state取数据都是先取出reducer或者reducer2模块,再取数据