1、context概念

context也就是上下文,方便子级组件共享数据,看个栗子就知道了

// 创建一个上下文
const context = React.createContext({count:0,add:function(){}});

// 提供者:提供数据
const Provider = context.Provider;
// 消费者:使用数据
const Consumer = context.Consumer;

const Child = (props: any) => {
    return <div>
        <span>{props.count}</span>
        <button onClick={props.add}>add</button>
    </div>;
};

const IndexView = () => {
    const [count, setCount] = useState(0);
    const add = () => {
        setCount(count + 1);
    };
    // 利用Provider和Consumer(可以多个)传输数据
    return <Provider value={{count, add}}>
        <Consumer>
            {
                <!-- 通过函数方式 -->
                value => <Child {...value}/>
            }
        </Consumer>
    </Provider>;
};

我们可以看出虽然Child可以获取到数据,但是使用并不方便,如果是多层子组件,就不好用了

二、useReducer

16.8以上react-hook中提供了useReducer方法很好的解决了这个问题,
用法如下

  • store 文件

    export const state = {
      name: 'lihaixing',
      age: 32,
      sons: []
    };
    
    export function Reducer(state, action) {
      if (!action.type && !action.data) {
          return {
              ...state,
              ...action
          };
      }
      switch (action.type) {
          case 'update':
              return {
                  ...state,
                  ...action.data
              };
          default:
              return state;
      }
    }
    // 上下文
    export const context = React.createContext({
      state, dispatch: (obj: any) => {}
    });
  • container组件

    import React, { useReducer } from 'react';
    import { state as initState, Reducer,context } from './store';
    
    import Com1 from './comp1'
    import Com2 from './comp2'
    
    const IndexView = () => {
      const [state, dispatch] = useReducer(Reducer, initState);
    
      return <context.Provider value={{ state, dispatch }}>
          <Com1 />
          <Com2 />
      </context.Provider>
    };
    
    export default IndexView;
  • comp1组件

    import React, { useContext } from 'react';
    import { context } from './index';
    
    const IndexView = () => {
      const {state, dispatch} = useContext(context);
      const {name, age, sons} = state;
      const setAge = () => {
          dispatch({age: age + 1});
      };
      const setSons = () => {
          dispatch({sons: [...sons, 1]});
      };
      return <div>
          {name} <br/>
          {age} <br/>
          {sons} <br/>
          <button onClick={setAge}>按钮age</button>
          <button onClick={setSons}>按钮sons</button>
      </div>;
    };
    
    export default IndexView;
  • comp2组件
import React, { useContext } from 'react';
import { context } from './index';

const IndexView = () => {
    const {state} = useContext(context);
    const {name, age, sons} = state;
    return <div>
        {name} <br/>
        {age} <br/>
        {sons} <br/>
    </div>;
};

export default IndexView;

总结:
1、useReducer使数据成为可维护的响应式数据,并且返回了dispatch方法
2、useContext使我们不需要通过Consumer传参,不管有几层子组件,只要把context引进来,利用useContext方法就能获取到响应式state数据和触发数据变化的dispatch方法

系列

重学react——slot
重学react——state和生命周期
重学react——redux
重学react——hooks以及原理
重学react——context/reducer
重学react——router
重学react——高阶组件
build your own react
React——fiber


lihaixing
463 声望719 粉丝

前端就爱瞎折腾