我已经实现了useContext+useReducer,并且我发现只有调度发生变化时才会重新呈现.

我可以有两个独立的组件,如果触发了一个调度,则两个组件都会更改.

示例:

enter image description here

每次状态更新时都会呈现递增和递减.

我找到了我关注的这article个,但我仍然得到了同样的结果.

代码:

export default function App() {
  return (
    <MyContextProvider>
      <Count />
      <ButtonIncrement /> <br /> <br />
      <ButtonDecrement />
    </MyContextProvider>
  );
}

提供者:

import * as React from 'react';
import {
  InitalState,
  ApplicationContextDispatch,
  ApplicationContextState,
} from './Context';
import { applicationReducer } from './Reducer';

export const MyContextProvider = ({ children }) => {
  const [state, dispatch] = React.useReducer(applicationReducer, InitalState);

  return (
    <ApplicationContextDispatch.Provider value={{ dispatch }}>
      <ApplicationContextState.Provider value={{ state }}>
        {children}
      </ApplicationContextState.Provider>
    </ApplicationContextDispatch.Provider>
  );
};

上下文:

import React, { Dispatch } from 'react';

export enum ApplicationActions {
  increment = 'increment',
  decrement = 'decrement',
  notification = 'Notification',
}

export type ActionType = ApplicationActions;

export const ActionTypes = { ...ApplicationActions };

export type StateType = {
  count: number;
  notification: string | undefined;
};

export type Action = {
  type: ActionType;
  payload?: string | undefined;
};

interface IContextPropsState {
  state: StateType;
}

interface IContextPropsDispatch {
  dispatch: Dispatch<Action>;
}

export const ApplicationContextState = React.createContext<IContextPropsState>(
  {} as IContextPropsState
);

export const ApplicationContextDispatch =
  React.createContext<IContextPropsDispatch>({} as IContextPropsDispatch);

export const useApplicationContextState = (): IContextPropsState => {
  return React.useContext(ApplicationContextState);
};

export const useApplicationContextDispatch = (): IContextPropsDispatch => {
  return React.useContext(ApplicationContextDispatch);
};

export const InitalState: StateType = {
  count: 0,
  notification: '',
};

异径管:

import { StateType, Action, ActionTypes } from './Context';

export const applicationReducer = (
  state: StateType,
  action: Action
): StateType => {
  const { type } = action;
  switch (type) {
    case ActionTypes.increment:
      return { ...state, count: state.count + 1 };
    case ActionTypes.decrement:
      return { ...state, count: state.count - 1 };
    case ActionTypes.notification:
      return { ...state, notification: action.payload };
    default:
      return state;
  }
};

工作示例here

在上面的文章中,这fiddle是作为我try 的一个例子,但我不知道我错在哪里.

请注意,这方面的原始示例没有使用TypeScrip,但在我的try 中,我将添加TypeScrip.

推荐答案

问题在于,您正在将一个新对象传递给上下文提供程序.这是个classic 的骗局.将对象作为props 传递意味着每次都传递一个新对象,这将导致props 引用判断失败.

dispatchstate直接传递给提供者,即value={dispatch}

https://reactjs.org/docs/context.html#caveats

Caveats

因为上下文使用引用标识来确定何时重新呈现,所以当提供者的父级重新呈现时,有一些trap 可能会在消费者中触发无意的呈现.例如,下面的代码将在每次提供程序重新呈现时重新呈现所有使用者,因为总是为Value创建新对象:

 <MyContext.Provider value={{something: 'something'}}>

Typescript相关问答推荐

类型是工作.但它失go 了正确变体的亮点..为什么?或者如何增强?

使用带有RxJS主题的服务在Angular中的组件之间传递数据

typescribe警告,explate—deps,useEffect依赖项列表

Webpack说你可能需要在Reactjs项目中增加一个加载器''

接口的额外属性作为同一接口的方法的参数类型'

如何在TypeScrip面向对象程序设计中用方法/属性有条件地扩展类

material 表不渲染任何数据

如何在Typescript 中输入两个相互关联的变量?

对数组或REST参数中的多个函数的S参数进行类型判断

如何使用Zod使一个基于其他字段值的字段为必填字段?

在不更改类型签名的情况下在数组并集上映射文字

<;T扩展布尔值>;

React Typescript项目问题有Redux-Toolkit userSlice角色问题

为什么不能使用$EVENT接收字符串数组?

一个打字类型可以实现一个接口吗?

在类型脚本中创建泛型类型以动态追加属性后缀

为什么我的查询钩子返回的结果与浏览器的网络选项卡中看到的结果不同?

显式推断对象为只读

如何向我的自定义样式组件声明 custom.d.ts ?

TS 排除带点符号的键