• 技术文章 >web前端 >js教程

    一文详解Redux Hooks的使用细节

    青灯夜游青灯夜游2022-11-11 18:24:47转载105
    本篇文章带大家聊聊Redux Hooks的使用细节,希望对大家有所帮助!

    大前端零基础入门到就业:进入学习

    Redux Hooks

    Redux中Hooks介绍

    在之前的redux开发中,为了让组件和redux结合起来,我们使用了react-redux库中的connect:

    但是这种方式必须使用高阶函数结合返回的高阶组件;

    并且必须编写:mapStateToProps和 mapDispatchToProps映射的函数, 具体使用方式在前面文章有讲解;【相关推荐:Redis视频教程编程视频

    在Redux7.1开始,提供了Hook的方式,在函数组件中再也不需要编写connect以及对应的映射函数了

    useSelector的作用是将state映射到组件中:

    参数一: 要求传入一个回调函数, 会将state传递到该回调函数中; 回调函数的返回值要求是一个对象, 在对象编写要使用的数据, 我们可以直接对这个返回的对象进行解构, 拿到我们要使用state中的数据

    const { counter } = useSelector((state) => {
      return {
        counter: state.counter.counter
      }
    })

    参数二: 可以进行比较来决定是否组件重新渲染;

    useSelector默认会比较我们返回的两个对象是否相等;

    如何可以比较呢?

    • 在useSelector的第二个参数中, 传入react-redux库中的shallowEqual函数就可以进行比较
    import { shallowEqual } from 'react-redux'
    
    const { counter } = useSelector((state) => ({
      counter: state.counter.counter
    }), shallowEqual)

    也就是我们必须返回两个完全相等的对象才可以不引起重新渲染;

    useDispatch非常简单,就是调用useDispatch这个Hook, 就可以直接获取到dispatch函数,之后在组件中直接使用即可;

    const dispatch = useDispatch()

    我们还可以通过useStore来获取当前的store对象(了解即可, 不建议直接操作store对象);


    Redux中Hooks使用

    我们来使用Redux的Hooks在App组件实现一个计数器, 在App的子组件中实现一个修改message的案例:

    首先我们先创建一个简单的store

    // store/modules/counter.js
    
    import { createSlice } from "@reduxjs/toolkit";
    
    const counterSlice = createSlice({
      name: "counter",
      initialState: {
        counter: 10,
        message: "Hello World"
      },
      reducers: {
        changeNumberAction(state, { payload }) {
          state.counter = state.counter + payload
        },
        changeMessageAction(state,  {payload }) {
          state.message = payload
        }
      }
    })
    
    export const { changeNumberAction, changeMessageAction } = counterSlice.actions
    
    export default counterSlice.reducer
    // store/index.js
    
    import { configureStore } from "@reduxjs/toolkit";
    import counterSlice from "./modules/counter"
    
    const store = configureStore({
      reducer: {
        counter: counterSlice
      }
    })
    
    export default store

    要使用react-redux库需要导入Provider对App组件进行包裹

    import React from "react"
    import ReactDOM from "react-dom/client"
    import { Provider } from "react-redux"
    import App from "./12_Redux中的Hooks/App"
    import store from "./12_Redux中的Hooks/store"
    
    const root = ReactDOM.createRoot(document.querySelector("#root"))
    
    root.render(
      <Provider store={store}>
        <App/>
      </Provider>
    )

    在组件时使用useSelector和useDispatch实现获取store中的数据和修改store中数据的操作

    import React, { memo } from 'react'
    import { useDispatch, useSelector } from 'react-redux'
    import { changeMessageAction, changeNumberAction } from './store/modules/counter'
    
    // 子组件Home
    const Home = memo(() => {
      console.log("Home组件重新渲染")
      
      // 通过useSelector获取到store中的数据
      const { message } = useSelector((state) => ({
        message: state.counter.message
      }))
    
      // useDispatch获取到dispatch函数
      const dispatch = useDispatch()
      function changeMessage() {
        dispatch(changeMessageAction("Hello ChenYq"))
      }
    
      return (
        <div>
          <h2>{message}</h2>
          <button onClick={changeMessage}>修改message</button>
        </div>
      )
    })
    
    
    // 根组件App
    const App = memo(() => {
      console.log("App组件重新渲染")
      
      // 通过useSelector获取到store中的数据
      const { counter } = useSelector((state) => ({
        counter: state.counter.counter
      }))
    
      // useDispatch获取到dispatch函数
      const dispatch = useDispatch()
      function changeNumber(num) {
        dispatch(changeNumberAction(num))
      }
      
      return (
        <div>
          <h2>当前计数: {counter}</h2>
          <button onClick={() => changeNumber(1)}>+1</button>
          <button onClick={() => changeNumber(-1)}>-1</button>
    
          <Home/>
        </div>
      )
    })
    
    export default App

    现在我们已经在组件中使用并且修改了了store中的数据, 但是现在还有一个小问题(性能优化)

    当App组件中修改了counter时, App组件会重新渲染这个是没问题的; 但是Home组件中使用的是message, 并没有使用counter, 却也会重新渲染; 同样的在Home子组件中修改了message, 根组件App也会重新渲染; 这是因为在默认情况下useSelector是监听的整个state, 当state发生改变就会导致组件重新渲染

    要解决这个问题就需要使用useSelector的第二个参数来控制是否需要重新渲染, 我们只需要在useSelector函数中传入react-redux库中的shallowEqual函数即可, 它内部会自动进行一个浅层比较, 当使用的state中的数据确实发生变化的时候才会重新渲染

    import React, { memo } from 'react'
    import { useDispatch, useSelector, shallowEqual } from 'react-redux'
    import { changeMessageAction, changeNumberAction } from './store/modules/counter'
    
    // 子组件Home
    const Home = memo(() => {
      console.log("Home组件重新渲染")
    
      const { message } = useSelector((state) => ({
        message: state.counter.message
      }), shallowEqual)
    
      const dispatch = useDispatch()
      function changeMessage() {
        dispatch(changeMessageAction("Hello ChenYq"))
      }
    
      return (
        <div>
          <h2>{message}</h2>
          <button onClick={changeMessage}>修改message</button>
        </div>
      )
    })
    
    
    // 根组件App
    const App = memo(() => {
      console.log("App组件重新渲染")
    
      // 通过useSelector获取到store中的数据
      const { counter } = useSelector((state) => ({
        counter: state.counter.counter
      }), shallowEqual)
    
      // useDispatch获取到dispatch函数
      const dispatch = useDispatch()
      function changeNumber(num) {
        dispatch(changeNumberAction(num))
      }
      
      return (
        <div>
          <h2>当前计数: {counter}</h2>
          <button onClick={() => changeNumber(1)}>+1</button>
          <button onClick={() => changeNumber(-1)}>-1</button>
    
          <Home/>
        </div>
      )
    })
    
    export default App

    更多编程相关知识,请访问:编程教学!!

    以上就是一文详解Redux Hooks的使用细节的详细内容,更多请关注php中文网其它相关文章!

    声明:本文转载于:csdn,如有侵犯,请联系admin@php.cn删除

    前端(VUE)零基础到就业课程:点击学习

    清晰的学习路线+老师随时辅导答疑

    快捷开发Web应用及小程序:点击使用

    支持亿级表,高并发,自动生成可视化后台。

    专题推荐:Hooks Redux React
    上一篇:浅析Nodejs中的http模块和导出共享 下一篇:自己动手写 PHP MVC 框架(40节精讲/巨细/新人进阶必看)

    相关文章推荐

    • ❤️‍🔥共22门课程,总价3725元,会员免费学• ❤️‍🔥接口自动化测试不想写代码?• 总结Vue创建响应式数据对象(reactive、ref、toRef、toRefs)• 详解vue3中reactive和ref的区别(源码解析)• 原理详解:Vue3中reactive和ref的区别• 什么是React高阶组件?怎么它创建一个面包屑导航?• 7 个很棒且实用的React 组件库(压箱底分享)
    1/1

    PHP中文网