React Hook--useReducer

478 阅读3分钟

useReducer

可以使用useReducer和useContext实现redux插件就可以统一管理组件状态的变换。

useReducer的使用

useReducer的使用和useState类似,都是用来管理组件状态。只不过和useState的setState不一样的是,useReducer返回的dispatch函数是用来触发某些改变state的action而不是直接设置state的值,至于不同的action如何产生新的state的值则在reducer函数中定义。useReducer刷新页面,当状态改变后使用了状态的地方就会重新取值页面就会重新渲染。

const [state, dispatch] = useReducer(reducer, initialArg, init);

第一个参数 reducer 是函数 (state, action) => newState,接受当前的 state 和当前dispatch的action为参数,然后返回下一个新的state,也就是说它负责状态变换的工作。

第二个参数 initialArg 是状态初始值。如果调用者没有提供第三个init参数,这个参数代表的是这个reducer的初始状态,如果init参数有被指定的话,initialArg会被作为参数传进init函数来生成初始状态。

第三个参数 init 是懒加载初始化函数,可选参数。该参数存在就由该参数的返回值决定reducer函数的初始状态。(initialArg) => initialState,即它会接收useReducer的第二个参数initialArg作为参数,并生成返回一个初始状态initialState。

每次调用dispatch就会执行reducer函数,并将dispatch传入的action传给reducer函数用于操作state的变换,reducer函数每次都会返回一个新的state

reducer函数第一次调用时使用第二个参数或第三个参数的值作为初始状态值

import {useReducer} from 'react'
export default function App() {
  let reducer=(initstate,action)=>{
    if(action.type=='CHANGEMSG'){
      initstate.msg=action.value;
    };
    initstate=JSON.parse(JSON.stringify(initstate));
    return initstate;
  }
  let [state,dispatch]=useReducer(reducer,{msg:'6ara'});
  console.log(state,777777);
  let change=()=>{
    dispatch({type:'CHANGEMSG',value:'6ara 4ever'});
  }
  return (
    <div>
      <h1>App组件</h1>
      <p>{state.msg}</p>
      <button onClick={change}>修改状态</button>
    </div>
  )
}

2.gif

useReducer和useContext实现redux插件

思路就是在根组件中使用useContext作为数据的提供者,就在根组件中使用useReducer来统一管理唯一的数据源。

// src/store/Context.jsx
import React from "react";
// 创建上下文对象
let Context=React.createContext(null);
export default Context;
// src/store/Index.jsx
import React, { useReducer } from 'react'
import Context from './Context.jsx'
export default function Index(props) {
    let reducer = (initstate, action) => {
        switch (action.type) {
            case "CHANGEMSG":
                initstate.msg = action.value
                break;
            case "CHANGEINFO":
                initstate.info = action.value
                break;
            default:
                break;
        }
        initstate = JSON.parse(JSON.stringify(initstate));
        return initstate;
    }
    let [store, dispatch] = useReducer(reducer, { msg: '6ara', info: 'yyds' })
    return (
        <Context.Provider value={[store, dispatch]}>
            {props.children}
        </Context.Provider>
    )
}
import React from 'react';//用于创建组件的
import ReactDOM from 'react-dom/client'; //用于渲染页面的
import Index from "./store/index.jsx"
import App from './App.jsx'  

const root = ReactDOM.createRoot(document.getElementById('root'));//关联页面的根元素
root.render(
    // 根组件就是Index,就是index.jsx文件返回的模板,而index.jsx文件的props.children就是App组件
    <Index>
        <App />
    </Index>
);

这样App组件的子组件也可以获取上下文对象的数据。

// App组件 
import {useContext} from 'react';
import Context from './store/Context.jsx';
import Des from './Des.jsx';
export default function App() {
  let [store,dispatch]=useContext(Context);
  console.log(store,666);
  let change=()=>{
    dispatch({type:'CHANGEMSG',value:'6ara 4ever'});
  }
  return (
    <div>
      <h1>App组件</h1>
      <p>{store.msg}--{store.info}</p>
      <button onClick={change}>修改状态msg</button>
      <Des></Des>
    </div>
  )
}


// Des组件
import React,{useContext} from 'react'
import Context from './store/Context.jsx';
export default function Des() {
  let [store,dispatch]=useContext(Context);
  let changeinfo=()=>{
    dispatch({type:'CHANGEINFO',value:'tiamo'})
  }
  return (
    <div>
        <h1>Des组件</h1>
        <p>{store.info}</p>
        <button onClick={changeinfo}>修改状态info</button>
    </div>
  )
}

2.gif

import React, { useReducer } from 'react'
import Context from './Context.jsx'
export default function Index(props) {
    let reducer = (initstate, action) => {
        switch (action.type) {
            case "CHANGEMSG":
                initstate.msg = action.value
                break;
            case "CHANGEINFO":
                initstate.info = action.value
                break;
            default:
                break;
        }
        initstate = JSON.parse(JSON.stringify(initstate));
        return initstate;
    }
    let [store, dispatch] = useReducer(reducer, { msg: '6ara', info: 'yyds' },function(arg){
        // arg就是{ msg: '6ara', info: 'yyds' }这个对象,可以处理该数据比如做网络请求等
        // 然后返回值就是仓库的初始状态
        return arg;
    })
    return (
        <Context.Provider value={[store, dispatch]}>
            {props.children}
        </Context.Provider>
    )
}