【问题标题】:Invalid hook call when setting up context with a reducer使用减速器设置上下文时挂钩调用无效
【发布时间】:2021-08-18 22:41:21
【问题描述】:

我正在尝试设置一个AppProvider 组件,该组件使用上下文和reducer 来处理我的应用程序的全局数据。然而,在AppProvider 中调用的useReducer 钩子似乎导致了错误。我已经阅读了the link in the error message,据我所知,我没有违反其中列出的任何规则。

import { merge } from 'lodash';
import React, { useReducer, Reducer, useContext, Dispatch } from 'react';

export interface AppState {
  stuff: string;
}
const initialState: AppState = { stuff: 'something' };
const AppStateContext = React.createContext(initialState);

export type Action = { type: 'SET_STATE'; state: Partial<AppState> };
const AppDispatchContext = React.createContext<Dispatch<Action>>(
  () => initialState,
);
const reducer: Reducer<AppState, Action> = (
  state: AppState,
  action: Action,
): AppState => {
  switch (action.type) {
    case 'SET_STATE':
      return { ...merge(state, action.state) };
    default:
      return { ...state };
  }
};

// eslint-disable-next-line @typescript-eslint/no-explicit-any
export type AppProviderProps = AppState & { children: any };
export const AppProvider = ({ children, ...rest }: AppProviderProps) => {
  const [state, dispatch] = useReducer(reducer, {
    ...initialState,
    ...rest,
  });

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

// Hooks
export const useAppContextState = (): AppState => useContext(AppStateContext);
export const useAppContextDispatch = (): React.Dispatch<Action> =>
  useContext(AppDispatchContext);

我将它与创建的新应用程序一起使用with create-react-app

import queryString from 'query-string';
import React from 'react';

import { AppProvider } from './app/AppProvider';
import logo from './logo.svg';
import './App.css';

function App() {
  const { stuff } = queryString.parse(document.location.search);

  if (typeof stuff !== 'string') {
    return (
      <div>
        Missing stuff parameter.
      </div>
    );
  }

  return (
    <AppProvider stuff={stuff}>
      <div className="App">
        <header className="App-header">
          <img src={logo} className="App-logo" alt="logo" />
          <p>
            Edit <code>src/App.tsx</code> and save to reload.
          </p>
          <a
            className="App-link"
            href="https://reactjs.org"
            target="_blank"
            rel="noopener noreferrer"
          >
            Learn React
          </a>
        </header>
      </div>
    </AppProvider>
  );
}

export default App;

抛出的错误:

软件包版本:

  • react@17.0.2(唯一安装的版本)
  • react-dom@17.0.2
  • react-scripts@4.0.3

【问题讨论】:

  • 通过这个stackoverflow.com/questions/53028117/…它可能会有所帮助
  • 你如何使用AppProvider
  • 有问题的代码可能在您使用&lt;AppProvider&gt; 的地方。你能出示这段代码吗?
  • 我在一个新的 create-react-app 的 App 组件中使用它。编辑添加App 组件。
  • 使用{ children: ReactNode }可以去掉eslint-disable

标签: javascript reactjs typescript react-hooks


【解决方案1】:

这个问题实际上是由安装了两个不同的react 软件包引起的。该应用程序是 monorepo 的一部分,并且 yarn 提升了 react-dom 包。解决方法是简单地防止提升reactreact-dom

package.json:

{
  "workspaces": {
    "packages": [
      "packages/*"
    ],
    "nohoist": [
      "**/react",
      "**/react/**",
      "**/react-dom",
      "**/react-dom/**",
    ]
  }
}

【讨论】:

    猜你喜欢
    • 2023-01-18
    • 2021-12-07
    • 1970-01-01
    • 2020-08-13
    • 2022-10-04
    • 1970-01-01
    • 2021-01-24
    • 2021-09-08
    • 1970-01-01
    相关资源
    最近更新 更多