自定义挂钩无法从上下文获取更新值

Ber*_*den 0 javascript reactjs react-context react-hooks

我正在尝试使用自定义挂钩来调用将用于多个组件和上下文的函数。但是,钩子永远不会更新上下文值,它始终是一个空数组,但在上下文中,用作上下文值的状态会被更新,并且在组件中会接收上下文值。这里发生了什么?

在我看来,上下文值没有被传递给钩子,但我不明白为什么。

这是我的代码示例:

语境:

import { createContext, useState, useEffect } from "react";
import useTest from "./useTest";

const TestContext = createContext({
  test: [],
  testContextFn: () => {}
});

export const TestProvider = ({ children }) => {
  const [testState, setTestState] = useState([]);

  const { testFn } = useTest();

  const testHandlerHandler = () => {
    const test = 1;
    setTestState((current) => [...current, test]);
    testFn();
  };

  const contextValue = {
    test: testState,
    testContextFn: testHandlerHandler
  };

  useEffect(() => {
    console.log("state: ", testState); // => gets the updated value
  }, [testState]);

  return (
    <TestContext.Provider value={contextValue}>{children}</TestContext.Provider>
  );
};
Run Code Online (Sandbox Code Playgroud)

钩:

import { useContext } from "react";

import { TestContext } from "./hooks/textContext";

const useTest = () => {
  const testCtx = useContext(TestContext);

  const testFn = () => {
    console.log("testCtx: ", testCtx.test); // => Always an empty array
  };

  return { testFn };
};

export default useTest;
Run Code Online (Sandbox Code Playgroud)

成分:

const App = () => {
  return (
    <TestProvider>
      <ExampleComponent />
    </TestProvider>
  );
};



const ExampleComponent = () => {
  const testCtx = useContext(TestContext);
    
 console.log("testCtx: ", testCtx.test); // => Gets the updated value

  return <div onClick={testCtx.testContextFn}>CLICK HERE</div>;
};
Run Code Online (Sandbox Code Playgroud)

在上下文中使用自定义挂钩时是否存在某种限制,或者我错过了什么?

小智 5

因此,上下文只能在提供程序的后代中使用,而不能在您的提供程序内部使用。因此,您应该将其从提供程序中删除,并在包装​​了提供程序的任何地方使用它。此外,最好使用您的上下文创建自定义挂钩并从同一提供程序文件中导出它。像这样的东西:

export function useTestContext() {
  const context = React.useContext(TestContext)
  if (context === undefined) {
    throw new Error('useTestContext must be used within TestProvider')
  }
  return context
}
Run Code Online (Sandbox Code Playgroud)