React Hook使用useContext和useReduce

2020-05-11  本文已影响0人  敏0321

useContext介绍

接收一个 context 对象(React.createContext 的返回值)并返回该 context 的当前值。

// MyContext由createContext()创建
let count = useContext(MyContext);

常用于容器组件向子组件传值

示例

这里以父组件向子组件传count累加值为例

定义容器组件

import { createContext } from "react";
export let MyContext = createContext();

定义子组件

import React, { useContext } from "react";
import { MyContext } from "./myContext";

export default () => {
  let count = useContext(MyContext);
  return (
    <h3>子组件{count}</h3>
  )
}

调用组件

import React, { createContext, useContext, useState } from "react";

import { MyContext } from "./myContext";
import { Button } from "antd";


function UseContext() {
  const [count, setCount] = useState(0);
  return (
    <>
      <MyContext.Provider value={count}>
        <ChildContext/>
      </MyContext.Provider>
      <Button type={"primary"} onClick={() => {
        setCount(count + 1);
      }}>
        change count
      </Button>
    </>
  )
}

export default UseContext;

useReducer介绍

类似于Redux数据流形式。使用state共享数据,dispatch触发数据修改。

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

useReducer接收3个参数:

  1. 接收一个函数,reducer对数据的具体操作。
  2. state初始值。
  3. 接收一个函数,用于state初始化。

示例

修改通过dispatch修改对象中属性为例。

import React, { useReducer } from "react";
import { Button } from "antd";

function UseReducer() {
  const [state, dispatch] = useReducer((state, action) => {
    switch (action.type) {
      case 'setName':
        return {
          ...state,
          name: action.name
        }
      default:
        return state;
    }
  }, { name: 'init' });
  return (
    <>
      <h1>{state.name}</h1>
      <Button type={"primary"} onClick={() => {
        dispatch({
          type: 'setName',
          name: 'hzm'
        })
      }}>setName</Button>
    </>
  )
}

export default UseReducer;

构建局部Reducer

大概介绍完useContext和useReducer用法,接下来开始进入正题。结合useContext和useReducer构建局部的Redux。
我们这里需要创建3个文件

  1. reduceAndContext.js (顶层组件,用于向下分发数据)
  2. reducer.js (reducer的具体操作)
  3. childReducer.js (子组件,向reducer发送dispatch)

reduceAndContext.js

import React from "react";
import { Reducer } from "./reducer";
import ChildReducer from "./childReducer";

function ReducerAndContext() {
  return (
    <Reducer>
      <ChildReducer/>
    </Reducer>
  )
}

export default ReducerAndContext;

reduceAndContext.js 中引入reducer.js和childReducer.js,让<Reducer>包裹下的<ChildReducer/>组件能接收到Reducer中的数据。

reducer.js

import React, { createContext, useReducer } from "react";

export const MyContext = createContext();

const reducer = (state, action) => {
  switch (action.type) {
    case 'setName':
      return {
        ...state,
        name: action.name
      }
    default:
      return state;
  }
}

const defaultData = {
  name: 'init',
}

export function Reducer(props) {
  const [state, dispatch] = useReducer(reducer, defaultData);
  return (
    <MyContext.Provider value={{ state, dispatch }}>
      {props.children}
    </MyContext.Provider>
  )
}

这里导出两个模块:

  1. MyContext (因为子组件使用useContext需要传入createContext,所以必须导出顶层组件创建的Context)
  2. Reducer (创建useReducer,并且把state和dispatch通过createContext提供的Provider形式传到子组件)
    由此,子组件就可以通过useContext使用父组件传过来的state和dispatch更新Reducer中的state数据。

childReducer.js

import React, { useContext } from "react";
import { MyContext } from "./reducer";
import { Button } from "antd";

function ChildReducer() {
  const { state, dispatch } = useContext(MyContext);
  return (
    <>
      <h1>{state.name}</h1>
      <Button type={"primary"} onClick={() => {
        dispatch({
          type: 'setName',
          name: 'hzm'
        })
      }}>
        change reducer
      </Button>
    </>
  )
}

export default ChildReducer;
上一篇 下一篇

猜你喜欢

热点阅读