• react hook中的状态管理方式


    1.useState

    (1)useState可以在react中进行简单的状态管理。

    import React, { useState } from "react";
    
    function Counter() {
       // 进行状态初始化
      const [count, setCount] = useState(0);
      return (
        <div className="App">
          count:{count}
          <button onClick={() => setCount(count + 1)}>+1</button>
        </div>
      );
    }
    
    export default Counter
    可以方便的使用定义好的setCount方法更新count的值。

    (2)使用对象

    如果遇到该组件中state数量比较大的时候,可能会出现下面这种情况:

    example:
    const [count1, setCount1] = useState(0);
    const [count2, setCount2] = useState(0);
    const [count3, setCount3] = useState(0);
    const [count4, setCount4] = useState(0);
    const [count5, setCount5] = useState(0);
    ……
    这个时候就觉得一条条的useState写起来十分繁琐,此时可以选择类似component组件this.state写法,将一些状态集中放在一个对象中,通过setCounts({...counts,……})的方式来更新状态。
    const [counts,setCounts]=useState({
        count1:0,
        count2:0,
        count3:0,
        count4:0,
        count5:0
        ……
      })
      
      ……
      
       <div className="App">
        <p>count:{count}</p> 
        <p>count1:{counts.count1}</p> 
        <p>count2:{counts.count2}</p> 
        <p>count3:{counts.count3}</p> 
        <p>count4:{counts.count4}</p> 
        <p>count5:{counts.count5}</p> 
        ……
        <button onClick={
            () => setCounts({...counts,count1:counts.count1+1})
            }>+1</button>
        </div>
    使用useState会发现状态更新的逻辑比较零散,分布在UI各处,且不便于测试。

    2.useReducer

    useReducer可以解决上面useState无法解决的问题。

    useRducer是useState的替代方案。它接收一个形如(state, action) => newState的reducer以及初始化对象,并返回当前的state以及配套的dispatch方法。
     
    某些场景下,useReducer 会比 useState 更适用,例如 state 逻辑较复杂且包含多个子值,或者下一个 state 依赖于之前的 state 等。并且,使用 useReducer 还能给那些会触发深更新的组件做性能优化,因为你可以向子组件传递 dispatch 而不是回调函数 。
    const [state, dispatch] = useReducer(reducer, initialArg, init);
    const initialState = {count: 0};
    
    function reducer(state, action) {
      switch (action.type) {
        case 'increment':
          return {count: state.count + 1};
        case 'decrement':
          return {count: state.count - 1};
        default:
          throw new Error();
      }
    }
    
    function Counter() {
      const [state, dispatch] = useReducer(reducer, initialState);
      return (
        <>
          Count: {state.count}
          <button onClick={() => dispatch({type: 'decrement'})}>-</button>
          <button onClick={() => dispatch({type: 'increment'})}>+</button>
        </>
      );
    }
    计数器代码经过useReducer改造后,乍一看代码反而更长了。但是如果在state 逻辑较复杂的场景下,效果就会体现出来:
    • 用useReducer将state集中在一起,会使state的逻辑更加有条理,我们能够清楚的了解到state的变化,可读性更好。
    • useReducer的逻辑脱离了UI,可以独立复用。
    • reducer是一个js方法,与UI无关,使我们更容易的进行自动化测试,也可以在chrome中进行调试。
     
    但是useReducer的局限也很明显:useReducer虽然很好的分离了逻辑和UI,但是无法进行跨组件的状态共享。

    3.useReducer和useContext使用

    useContext可以对它所包裹的组件树提供全局共享数据。

     接收一个 context 对象(React.createContext 的返回值)并返回该 context 的当前值。当前的 context 值由上层组件中距离当前组件最近的 <MyContext.Provider> 的 value prop 决定

    const value = useContext(MyContext);
    import React,{useReducer,useContext} from 'react';
    
    const initialState = {count: 0};
    function reducer(state, action) {
      switch (action.type) {
        case 'increment':
          return {count: state.count + 1};
        case 'decrement':
          return {count: state.count - 1};
        default:
          throw new Error();
      }
    }
    // 定义context
    const Ctx=React.createContext(null);
    
    const Parent=()=>{
        const [count,dispatch]=useReducer(reducer,initialState);
        return (
            // 在这里向子组件传递ctx
            <Ctx.Provider value={[count,dispatch]}>
            <div>
                parent:{count}
                <Child />
            </div>
            </Ctx.Provider>
        )
    }
    
    const Child=()=>{
        //在这里使用context
        const [count,dispatch]=useContext(Ctx);
        return (
            <div>
                child:count:{count}
                <button onClick={()=>dispatch({type:'increment'})}>+1</button>
                <button onClick={()=>dispatch({type:'decrement'})}>-1</button>
            </div>
            
        )
    }
    
    
    
    
    
    export default function App(){
        return <Parent />
    }
    如果我们的组件层级较深,且涉及父子组件传值,可以考虑这种方式。
     
    其中可能涉及到性能优化,可以使用useCallback来减少不必要的渲染。

    4.useSelector、useDispatch配合redux进行状态共享

    通常在react组件中使用redux,需要用provider、connect包裹react组件,还有mapState、mapDispatch 等固定的代码,才能使用store中的state和action。
     
    react-redux在7.1之后,可以使用useSelector、useDispatch等HooksApi替代connect,可以减少模板代码。

    (1)创建并引入redux的store

    import { createStore } from 'redux'; // redux
    import { Provider } from 'react-redux';
    const initialState = {count: 0};
    
    function reducer(state, action) {
      switch (action.type) {
        case 'increment':
          return {count: state.count + 1};
        case 'decrement':
          return {count: state.count - 1};
        default:
          throw new Error();
      }
    }
    
    const stores = createStores(reducer,initialState );
    
    function App() {
      return (
          <Provider store={stores}>
            <Router />
          </Provider>
      );
    }
    
    export default App;

    (2)useSelector

    可以访问到store中的各种状态
    const count=useSelector(state=>state.count)

    (3) useDispatch

    可以获取到dispatch

     const dispatch=useDispatch();
    import React from 'react'
    import { useSelector, useDispatch } from 'react-redux'
    
    function Counter() {
      const count=useSelector(state=>state.count)
      const dispatch = useDispatch()
      return (
        <div>
        <p>count:{count}</p>
        <button onClick={()=>dispatch({type:'increment'})}>+1</button>
        </div>
      );
    }
    
    export default Counter;

    5.其他方法

    除了Redux之外,现在还有很多适用于hook的状态管理工具:hox、stamen、icestore……

     6.参考链接

    https://juejin.cn/post/6844903869609148430

    https://juejin.cn/post/6844903817981460493

    https://zh-hans.reactjs.org/docs/

    https://blog.csdn.net/vitaviva/article/details/104508139

  • 相关阅读:
    GateWay的简单使用
    SpringCloud项目注册到Nacos
    Hystrix整合Gateway
    Nginx配置socket.io集群
    windows搭建git服务
    解决gitLab上新建分支,idea中找不到对应分支问题
    mybatis mapper.xml的特殊操作符
    Chrome添加Axure RP插件
    idea Tomcat部署时没有update classes and resources
    缓存穿透,缓存击穿,缓存雪崩解决方案分析【转载】
  • 原文地址:https://www.cnblogs.com/ellen-mylife/p/15324443.html
Copyright © 2020-2023  润新知