[英]React how to set context from a function. Invalid hook call
我无法从不在组件中的 function 检索上下文值。 我收到以下异常:
未捕获(承诺)错误:挂钩调用无效。 钩子只能在 function 组件的内部调用。 这可能由于以下原因之一而发生......
我已经声明了我的上下文。
export const ErrorContext = createContext({})
export const UseErrorContext = () => useContext(ErrorContext)
在我的 App.js 中设置一个提供者
<ErrorContext.Provider value={{ errorMessage }}>
</ErrorContext.Provider>
并且喜欢像这样从 function 设置值。 但这会导致上面的异常。 这个 function 在一个单独的文件中,并从不同的组件调用。
export const MyFunction = async (id) => {
const { errorMessage } = UseErrorContext();
errorMessage = "SOME ERROR MESSAGE";
}
您将无法以这种方式执行此操作:您不能在 React 的渲染阶段之外调用挂钩。
此外,即使您这样调用它,赋值也是局部的,不会影响上下文值。
要实现您想要的行为,您需要:
是这样的:
// context
export let ErrorContext = createContext({})
export let useErrorContext = () => useContext(ErrorContext)
// provider
let [errorMessage, setErrorMessage] = useState();
let value = useMemo(() => ({errorMessage, setErrorMessage}), [errorMessage])
<ErrorContext.Provider value={value}>
{children}
</ErrorContext.Provider>
// component
let {setErrorMessage} = useErrorContext();
export const myFunction = async (id, setErrorMessage) => {
setErrorMessage("SOME ERROR MESSAGE");
}
// later, in an event:
myFunction(id, setErrorMessage);
PS:此解决方案要求您为每个错误消息执行一个提供程序,以便您可以有多个,或者您应该更改抽象。
另一个解决方案看起来像是对我自己的库的提升,但事实并非如此,只是为了展示它解决这个问题的难易程度:
yarn add -D async-states react-async-states
import {useAsyncState, createSource} from "react-async-states"
// myErrorMessage should be unique, or else the library will warn
let myErrorMessageSource= createSource("myErrorMessage");
// in your component
let {state, setState} = useAsyncState(myErrorMessageSource);
// then use the state.data to display it
// in your async function, and your component would react to it
myErrorMessageSource.setState("SOME ERROR MESSAGE");
这只是库的一个基本用例,请在选择它之前阅读文档。
正如错误所说:
钩子只能在 function 组件的内部调用
我的建议是创建您的自定义挂钩
一个自定义 Hook 是一个 JavaScript function 其名称以“use”开头并且可能调用其他 Hook。
现在这是可能的
export const useMyFunction = async (id) => {
const { errorMessage } = UseErrorContext();
...
}
确保只在自定义 Hook 的顶层无条件地调用其他 Hook。
从另一个组件调用自定义挂钩时相同
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.