Hook钩子函数--useReducer

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

 

 




上一篇:iOS基础 - 线程 1.3:NSObject | GCD


下一篇:React_04_Redux