反应useContext + TypeScript范围错误

时间:2020-05-09 11:54:34

标签: javascript reactjs typescript react-hooks react-context

首次尝试使用context / hooksTypeScript。因为我要发送值一个函数(调度/设置函数),所以我使用的是this blog post, under the header "Pattern B - A Separation"中概述的Provider分离模式。

只要我导出StateContextDispatchContext对象并导入它们以使其与消费组件中的useContext一起使用,以下设置就会按预期工作。

    // src/components/index.tsx
    ReactDOM.render(
      <Router>
        <MyProvider>
          <MyComponent />
        </MyProvider>
      </Router>,
      document.getElementById("root")
    );
    // src/providers/myProvider.tsx
    import React, { useState, useContext } from "react";

    type MyProviderProps = { children: React.ReactNode };
    type State = string | undefined;
    type Dispatch = (value: State) => void;

    export const StateContext = React.createContext<State>(undefined);
    export const DispatchContext = React.createContext<Dispatch | undefined>(undefined);

    export function MyProvider({ children }: MyProviderProps) {
      const [state, dispatch] = useState<State>(undefined);

      return (
        <StateContext.Provider value={state}>
          <DispatchContext.Provider value={dispatch}>
            {children}
          </DispatchContext.Provider>
        </StateContext.Provider>
      );
    }
    // src/components/MyComponent.tsx
    import React from "react";
    import {
      StateContext,
      DispatchContext,
    } from "../providers/myProvider";

    export default function MyComponent() {
      const myMessage = React.useContext(StateContext);
      const setMyMessage = React.useContext(DispatchContext);


      return (
        <div>{myMessage}</div>
      );
    }

但是,如果我尝试为useContext(XyzContext)创建辅助函数,则会收到错误消息,因为上下文为undefineduseMyMessage must be used within MyProvider。我不知道为什么此辅助功能会导致问题。

    // src/providers/myProvider.tsx
    import React, { useState, useContext } from "react";

    type MyProviderProps = { children: React.ReactNode };
    type State = string | undefined;
    type Dispatch = (value: State) => void;

    const StateContext = React.createContext<State>(undefined);
    const DispatchContext = React.createContext<Dispatch | undefined>(undefined);

    export function MyProvider({ children }: MyProviderProps) {
      const [state, dispatch] = useState<State>(undefined);

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

    export function useMyMessage() {
      const context = useContext(StateContext);
      if (!context) {
        throw new Error("useMyMessage must be used within MyProvider");
      }
      return context;
    }
    // src/components/MyComponent.tsx
    import React from "react";
    import {
      useMyMessage,
      DispatchContext,
    } from "../providers/myProvider";

    export default function MyComponent() {
      const myMessage = useMyMessage();
      const setMyMessage = React.useContext(DispatchContext);


      return (
        <div>{myMessage}</div>
      );
    }

0 个答案:

没有答案