React 中使用Redux方式方法

108 阅读4分钟

react-redux的使用

  1. redux和react没有直接的关系 可以在任何的框架中(Angular, Ember, jQuery,JS,Vue)使用redux
  2. 尽管这样说 redux依然是和React库结合的更好,因为他们是通过state函数来描述界面的状态,Redux可以发射状态的更新(dispatch), 让他们作出相应。
  • 在跟组件上 使用Provider 来给根组件进行包裹 传入对应的store
  • connect 函数本身返回值就是一个高阶组件 所以需要进行给connect返回值传参connect(参数)(组件)
  • connect会通过高阶函数 获取到他的参数以及组件本身的props 全部返回到组件内部的props
  • connect 参数
    • 参数1 需要传入一个函数(接受state值) 并且返回值是一个对象 对象内容是当前**映射(使用)**的字段值
    • 参数2 需要传入一个函数(接受dispatch值) 并且返回值是一个对象 对象内容函数 dispatch的方法名
    • 都是可以在组件内部 通过props来进行使用 这就是一个解藕操作
import React from 'react';
import ReactDOM from 'react-dom/client';
import App from './App';
import { Provider } from "react-redux"

// 通过redux创建出来的store
import store from "./store"

const root = ReactDOM.createRoot(document.getElementById('root'));
root.render(
  // <React.StrictMode>
    <Provider store={store}>
      <App />
    </Provider>
  // </React.StrictMode>
);

子组件
import React, { PureComponent } from 'react'
import { connect } from "react-redux"
import { fetchHomeMultidataAction } from "../store/actionCreators"

export class Category extends PureComponent {

  componentDidMount() {
    this.props.fetchHomeMultidata()
  }

  render() {
    return (
      <div>
        <h2>Category Page: {this.props.counter}</h2>
      </div>
    )
  }
}

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

const mapDispatchToProps = (dispatch) => ({
  fetchHomeMultidata() {
  // 因为对象没有作用域 所以当找dispatch 可以通过上面的dispatch
    dispatch(fetchHomeMultidataAction())
  }
})

export default connect(mapStateToProps, mapDispatchToProps )(Category)

redux-thunk: 在redux使用中间件进行异步操作

  • 在我们开发中,公共部分的网络请求到的数据也属于我们状态管理的一部分,更好的一种方式应该是将其也交给redux来管理;
  • 但是在dispatch派发中 如果直接进行异步操作 这样会拿不到请求结果。并且在dispatch中必须返回一个对象
  • 所以就需要使用中间件(MiddlewareMiddleware可以帮助我们在请求和响应之间嵌入一些操作的代码(redux-thunk)
  • 这个中间件的主要目的就是在dispatch的action和最终达成的reducer之间 扩展自己的代码
  • 在默认情况下 dispatch派发的action是一个对象 使用了redux-thunk 就可以让action是一个函数 并且该函数会被自动调用一次 并且传递给函数有两个参数
    • dispatch 用于我们之后再次派发
    • getState 考虑到在函数中需要使用到state 可以来进行获取之前的一些状态
import { createStore, applyMiddleware, compose } from "redux"
import thunk from "redux-thunk"
import reducer from "./reducer"

// 正常情况下 store.dispatch(object)
// 想要派发函数 store.dispatch(function)
applyMiddleware 使用中间件
thunk 具体使用的哪个中间件
const store = createStore(reducer, composeEnhancers(applyMiddleware(thunk)))

export default store



// dispatch 派发的action
export const fetchHomeMultidataAction = () => {
  // 如果是一个普通的action, 那么我们这里需要返回action对象
  // 问题: 对象中是不能直接拿到从服务器请求的异步数据的
  // return {}

  return function(dispatch, getState) {
    // 异步操作: 网络请求
    // console.log("foo function execution-----", getState().counter)
    axios.get("http://123.207.32.32:8000/home/multidata").then(res => {
      const banners = res.data.data.banner.list
      const recommends = res.data.data.recommend.list

      // dispatch({ type: actionTypes.CHANGE_BANNERS, banners })
      // dispatch({ type: actionTypes.CHANGE_RECOMMENDS, recommends })
      dispatch(changeBannersAction(banners))
      dispatch(changeRecommendsAction(recommends))
    })
  }

  // 如果返回的是一个函数, 那么redux是不支持的
  // return foo
}



//子页面调用

import React, { PureComponent } from 'react'
import { connect } from "react-redux"
import { fetchHomeMultidataAction } from "../store/actionCreators"

export class Category extends PureComponent {

  componentDidMount() {
    this.props.fetchHomeMultidata()
  }

  render() {
    return (
      <div>
        <h2>Category Page: {this.props.counter}</h2>
      </div>
    )
  }
}


const mapDispatchToProps = (dispatch) => ({
  fetchHomeMultidata() {
    dispatch(fetchHomeMultidataAction())
  }
})

export default connect(mapStateToProps, mapDispatchToProps )(Category)

redux -devtool 需要手动开启

// redux-devtools
const composeEnhancers = window.__REDUX_DEVTOOLS_EXTENSION_COMPOSE__({trace: true}) || compose;
const store = createStore(reducer, composeEnhancers(applyMiddleware(thunk)))

Reducer代码拆分

  • 因为reducer处理着更新state的变化 所以随着项目的日趋庞大 必然会造成代码的臃肿 难以维护
  • 我们可以拆分一个业务为一个模块

image.png

  • 可以通过redux提供的一个combineReducers函数 方便让我们对多个reducer进行拆分 image.png
  • 其内部远离 其实就是把传入的对象合并成一个对象中 composeEnhancers 函数(相当于reducer)
  • 在函数执行过程中会通过判断前后返回的数据是否相同来决定返回之前的state还是新的state
  • 新的state会触发订阅者发生对应的刷新,而旧的state可以有效的组织订阅者发生刷新