React-Redux使用

224 阅读4分钟

redux和react没有直接的关系,你完全可以在React, Angular, Ember, jQuery, or vanilla JavaScript中使用Redux

一、 安装

上一篇示例中使用了redux,但是对于监听store数据改变 派发事件(dispatch),等这些操作出现公共复杂引入调用,redux官方帮助我们提供了 react-redux 的库,可以直接在项目中使用,并且实现的逻辑会更加的严谨和高效

npm install react-redux

1.1 使用 Provider 透传 Store★★★

使用 <Provider> 组件包裹 <App> 组件,并将 Redux store 作为 prop 传递给 <Provider> 组件。之后,应用程序中的每个组件都可以在需要时能够访问到 Redux store

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

const root = ReactDOM.createRoot(document.getElementById('root'));
root.render(
  <React.StrictMode>
    // 使用 `<Provider>` 组件包裹 `<App>` 组件  
    // 并把 Redux store 作为 prop 传入
    <Provider store={store}>
      <App />
    </Provider>

  </React.StrictMode>
);

1.2 connect()高阶函数★★★

connect() 函数将 React 组件连接到 React store。

function connect(mapStateToProps?, mapDispatchToProps?, mergeProps?, options?)
  • mapStateToProps 和 mapDispatchToProps 分别处理 Redux store 的 state 和 dispatchstate 和 dispatch 将作为第一个参数提供给 mapStateToProps 或 mapDispatchToProps 函数。
  • 在内部,mapStateToProps 和 mapDispatchToProps 的返回值分别称为 stateProps 和 dispatchProps。如果定义了,它们将作为第一个和第二个参数提供给 mergeProps,其中第三个参数将是 ownProps。组合的结果通常称为 mergedProps,将提供给连接的组件。
import React, { PureComponent } from 'react'
import { connect } from 'react-redux'
import { powerNumAction } from '../store/actionCreators'

export class Home extends PureComponent {
  poweClick(num){
    this.props.powerNumAction(num)
  }
  render() {
    const { counter } = this.props
    return (
      <>
      Home账号文章:{counter}
      <div>
          <button onClick={e => this.poweClick(2)}>*2</button>
          <button onClick={e => this.poweClick(3)}>*3</button>
          <button onClick={e => this.poweClick(4)}>*4</button>
        </div>
      </>
    )
  }
}

//像高阶组件传输参数一样进行编写上文使用
const mapStateToProps = (state) => ({ counter: state.counter })

const mapDispatchToProps = (dispatch) => {
  return {
    // dispatch 普通的 action
    //来源参考下图
    powerNumAction: (num) => dispatch(powerNumAction(num)),
  }
}

//connect()返回值是一个高阶组件,
export default connect(mapStateToProps,mapDispatchToProps)(Home)

image.png 上文用例也可用Hooks来使用,但是要在函数式组件中使用

更新数据同时可以使用异步请求获取数据存储在state中:异步获取数据一般在生命周期componentDidMount中进行操作一般做法和上例一样。

优化后使用中间件来进行操作数据转发

二、 异步数据管理redux-thunk★★★

须知:异步请求操作数据一般用在网络请求等应用场景,因此我们需要一个中间件来进行异步操作。

  • 这个中间件的目的是在dispatch的action最终达到的reducer之间,扩展一些自己的代码;
  • 比如日志记录、调用异步接口、添加代码调试功能等等;

安装:npm install redux-thunk

  • 上文使用dispatch({...})是需要进行传入对象
  • 但是需要在store.dispatch(function)中派发函数:
    • 本质上使用redux-thunk工具库会对dispatch进行拦截,该库会进行判断传入的参数具体是什么类型,若是函数就进行执行函数
  • 进行网络请求一般进行抽取,但是上文提出是在组件中进行网络请求后进行修改,这里提出示例进行抽取
  • 放在redux中进行数据请求后分发

使用applyMiddleware | Redux 中文官网

因此使用redux-trunk做为中间件使用

store/index.js

import { createStore,applyMiddleware } from "redux";
import {thunk} from 'redux-thunk'
import { reducer } from "./reducer";

const store = createStore(reducer,applyMiddleware(thunk))
export default store

store/actionCreators.js

import { COUNT_CHANGE,ARRAY_CHANGE } from "./constants";
import axios from 'axios'
export const countChange=(count)=>({type:COUNT_CHANGE,count})
export const arrayChange=(arrayList)=>({type:ARRAY_CHANGE,arrayList})
export const fetchNetData=()=>{
  
  return function(dispatch, getState){
    axios.get("接口地址").then(({data})=>{
      console.log(data);
      dispatch(arrayChange(data.data.list))
    })
  }
}

其它调用逻辑都是和上文介绍相同

三、combineReducers(reducers)

当我们在项目中如果多个模块使用数据状态管理那么就需要多个文件进行拆分不同store最后再合并成一个出口去使用,类似于vuex中的模块化管理类似。需要用到该函数

随着应用变得越来越复杂,可以考虑将 reducer 函数 拆分成多个单独的函数,拆分后的每个函数负责独立管理 state 的一部分

由 combineReducers() 返回的 state 对象,会将传入的每个 reducer 返回的 state 按其传递给 combineReducers() 时对应的 key 进行命名

3.3 redux-devtools 在redux中继承devtools

import { createStore,applyMiddleware,compose, combineReducers } from "redux";
import {thunk} from 'redux-thunk'
import { reducer } from "./reducer"
//开启redux工具调试
const composeEnhancers = window.__REDUX_DEVTOOLS_EXTENSION_COMPOSE__ || compose;
//这里只演示了单个作为模块使用,多个的话可以继续对象追加包括,取用也需要用此名字
const rootReducer = combineReducers({count: reducer})//像vue中模块化管理类似需要进行包括一层
const store = createStore(rootReducer,composeEnhancers(applyMiddleware(thunk)))
export default store

未完待续。。。