• 微信公众号:美女很有趣。 工作之余,放松一下,关注即送10G+美女照片!

Hook钩子函数–useReducer

开发技术 开发技术 3小时前 3次浏览

1.介绍

(1)作用:“勾住”某些自定义数据对应的dispatch所引发的数据更改事件。useReducer可以替代useState,实现更为复杂逻辑的数据修改。  

(2)解决什么问题:useReducer是useState的升级版(实际上应该是原始版),可以实现复杂逻辑修改,而不是像useState那样只是直接赋值修改。

2.useReducer基础用法

useReducer(reducer,initialValue)函数通常传入2个参数,第1个参数为我们定义的一个“由dispatch引发的数据修改处理函数”,第2个参数为自定义数据的默认值,useReducer函数会返回自定义变量的引用和该自定义变量对应的“dispatch”。  
 
  import React, { useReducer } from ‘react’; //引入useReducer
   
    //定义好“事件处理函数” reducer
    function reducer(state, action) {
      switch (action) {
        case ‘xx’:
            return xxxx;
        case ‘xx’:
            return xxxx;
        default:
            return xxxx;
      }
    }

    function Component(){
      //声明一个变量xxx,以及对应修改xxx的dispatch
      //将事件处理函数reducer和默认值initialValue作为参数传递给useReducer
      const [xxx, dispatch] = useReducer(reducer, initialValue);

      //若想获取xxx的值,直接使用xxx即可
     
      //若想修改xxx的值,通过dispatch来修改
      dispatch(‘xx’);
    }
3.基础案例:

若某React组件内部有一个变量count,默认值为0,有3个button,点击之后分别可以修改count的值。3个按钮具体的功能为:第1个button点击之后count+1,第2个button点击之后count -1,第3个button点击之后 count x 2 (翻倍)。
 

    import React, { useReducer } from ‘react’;

    function reducer(state,action){
      switch(action){
        case ‘add’:
            return state + 1;
        case ‘sub’:
            return state – 1;
        case ‘mul’:
            return state * 2;
        default:
            console.log(‘what?’);
            return state;
      }
    }

    function CountComponent() {
      const [count, dispatch] = useReducer(reducer,0);

      return <div>
        {count}
        <button onClick={() => {dispatch(‘add’)}} >add</button>
        <button onClick={() => {dispatch(‘sub’)}} >sub</button>
        <button onClick={() => {dispatch(‘mul’)}} >mul</button>
      </div>;
    }

    export default CountComponent;
 
如果希望按钮点击之后,能够自主的控制增加多少,减少多少,或者乘以多少
 

  import React, { useReducer } from ‘react’;

    function reducer(state,action){
      //根据action.type来判断该执行哪种修改
      switch(action.type){
        case ‘add’:
          //count 最终加多少,取决于 action.param 的值
          return state + action.param;
        case ‘sub’:
          return state – action.param;
        case ‘mul’:
          return state * action.param;
        default:
          console.log(‘what?’);
          return state;
      }
    }

    function getRandom(){
      return Math.floor(Math.random()*10);
    }

    function CountComponent() {
      const [count, dispatch] = useReducer(reducer,0);

      return <div>
        {count}
        <button onClick={() => {dispatch({type:’add’,param:getRandom()})}} >add</button>
        <button onClick={() => {dispatch({type:’sub’,param:getRandom()})}} >sub</button>
        <button onClick={() => {dispatch({type:’mul’,param:getRandom()})}} >mul</button>
      </div>;
    }

    export default CountComponent;
 
 4.useReducer高级用法
(1)使用useReducer来管理复杂类型的数据
   

举例,若某组件内通过ajax请求数据,获取最新一条站内短信文字,需要组件显示整个ajax过程及结果:  
①当ajax开始请求时,界面显示“loading…”;  
②当ajax请求发生错误时,界面显示“wrong!”;  
③当ajax请求成功获取数据时,界面显示获取到的数据内容;
伪代码:
    const initralData = {loading: true,result: ”,error: false};
    const reducer = (state, action) => {
      switch (action.type) {
        case ‘succes’:
            return {loading:false,result:action.res,error:false}
        case ‘error’:
            return {loading:false,error:true}
      }
    }
   
    function Component() {
      const [state, dispatch] = useReducer(reducer, initralData);
   
      {
          //ajax请求成功情况下
          dispatch({type:’succes’,res:’You have a good news!’});
   
          //ajax请求错误情况下
          dispatch({type:’error’});
      }
   
      return <div>
        {state.loading ? ‘loading…’ : state.result}
        {state.error ? ‘wrong!’ : null}
      </div>
    }
 
(2)使用useContext和useReducer实现全局共享数据
实现的原理:用useContext实现“获取全局数据”;用userReducer实现“修改全局数据”
实现的思路:① 用React.createContext()定义一个全局数据对象
                      ②在父组件中用userReducer定义全局变量xx和负责抛出事件的dispatch
                      ③在父组件之外,定义负责具体修改全局变量的处理函数reducer,根据修改xx事件类型和参数,执行修改xx的值
                      ④在父组件中用<XxxContext.Provider value={{xx,dispathc}}>标签把全局共享数据和负责抛出修改xx的dispatch暴露给子组件
                      ⑤在子组件中用useContext获取全局变量
                      ⑥在子组件中用xxContext.dispatch去抛出修改xx的事件,携带修改事件类型和参数
假如有全局变量数据count,有不同的子组件均可以获取并且修改全局变量count
CountContext.js:
①共享对象:

    import React from ‘react’;
    const CountContext = React.createContext();
    export default CountContext;
父组件:
import React, { useReducer } from ‘react’;
import CountContext from ‘./CountContext’;
import ComponentA from ‘./ComponentA’;
import ComponentB from ‘./ComponentB’;
import ComponentC from ‘./ComponentC’;

const initialCount = 0; //定义count的默认值
 
// 修改count事件处理函数,根据u修改参数进行处理
//③在父组件之外,定义负责具体修改全局变量的处理函数reducer,根据修改xx事件类型和参数,执行修改xx的值;
function reducer(state, action) {
    switch (action.type) {
        case ‘add’:
            return state + action.param;
        case ‘sub’:
            return state – action.param;
        case ‘mul’:
            return state * action.param;
        case ‘reset’:
            return initialCount;
        default:
            console.log(“what?”);
            return state;
    }
}
export default function father() {
// ②在父组件中用 userReducer 定义全局变量count和负责抛出修事件的dispatch;
    const [count, dispatch] = useReducer(reducer, initialCount);
    // value={{ count, dispatch }是整个代码的核心,把将count、dispatch暴露给所有的子组件
    // ④在父组件中用 <XxxContext.Provider value={{xx,dispathc}}> 标签把 全局共享数据和负责抛出修改xx的dispatch 暴露给子组件;  
    return <CountContext.Provider value={{ count, dispatch }}>
        <div>
            ParentComponent – count = {count}
            <ComponentA />
            <ComponentB />
            <ComponentC/>
        </div>
        </CountContext.Provider>
}
子组件:
import React,{ useState, useContext } from ‘react’;
import CountContext from ‘./CountContext’;
export default function ComponentA() {
    const [param, setParam] = useState(1);
    // 引入全局共享对象,获取全局变量count,以及修改count对应的dispatch
    //⑤在子组件中用 useContext 获取全局变量;
    const countContext = useContext(CountContext)
    const inputChangeHandler = (eve) => {
        setParam(eve.target.value)
    }
    const doHandler = () => {
        //若想修改全局count,先获取count对应的修改抛出事件对象dispatch,然后通过dispatch将修改内容抛出
        //抛出的修改内容为:{type:’add’,param:xxx},即告诉count的修改事件处理函数,本次修改的类型为add,参数是param
        //这里的add和param完全是根据自己实际需求自己定义的
        // ⑥在子组件中用 xxContext.dispatch 去抛出修改xx的事件,携带修改事件类型和参数;
        countContext.dispatch({type:’add’,param:Number(param)});
      }
   
    const resetHandler = () => {
        //⑥在子组件中用 xxContext.dispatch 去抛出修改xx的事件,携带修改事件类型和参数;
        countContext.dispatch({type:’reset’});
    }
    return <div>
    ComponentA – count={countContext.count}
    <input type=’number’ value={param} onChange={inputChangeHandler} />
    <button onClick={doHandler}>add {param}</button>
    <button onClick={resetHandler}>reset</button>
</div>
   
}
Hook钩子函数--useReducer

 

 


程序员灯塔
转载请注明原文链接:Hook钩子函数–useReducer
喜欢 (0)