reactjs - 无法从上下文提供者获取钩子
问题描述
const mainState = (initial: number | null = null) => {
const [edit, setEdit] = React.useState<number | null>(initial)
return {
edit,
clear: () => setEdit(null)
}
}
const MainContext = React.createContext<ReturnType<typeof mainState> | null>(null)
export const useMainContext = () => React.useContext(MainContext)
export function MainProvider({ children }: { children: React.ReactNode }) {
return (
<MainContext.Provider value={mainState()}>{children}</MainContext.Provider>
)
}
然后我将整个应用程序包装在提供程序中
import React from 'react'
import ReactDom from 'react-dom'
import { MainProvider } from './store'
import { App } from './app'
ReactDom.render(
<MainProvider>
<App />
</MainProvider>,
document.getElementById('root')
)
但是当我尝试获取钩子 TypeScript 错误时
Property 'edit' does not exist on type '{ edit: number | null; clear: () => void; } | null'
import * as React from 'react'
import { useMainContext } from './store'
export const App = () => {
const { edit } = useMainContext()
...
}
解决方案
正如 Typescript 告诉您的那样,您的上下文类型可以是null
或{ edit: number | null; clear: () => void; }
记住您最初将其设置为:const MainContext = React.createContext<ReturnType<typeof mainState> | null>(null)
.
你不能解构 null 所以这就是 Typescript 不高兴的原因。要么你不使用解构:
const context = useMainContext()
context?.edit
或者您将上下文设置为具有编辑默认值的不同值。
我刚刚注意到 mainState 正在使用 useState 但 mainState 似乎既不是自定义反应钩子也不是组件。反应文档指出自定义反应钩子应该以use
. 并且必须在另一个自定义反应钩子或组件中使用钩子。
因此,修复代码的一种方法是:
const useMainState = (initial: number | null = null) => { // this is now a custom react hook
const [edit, setEdit] = React.useState<number | null>(initial)
return {
edit,
clear: () => setEdit(null)
}
}
export function MainProvider({ children }: { children: React.ReactNode }) {
// it's called in a component, Ok
const mainState = useMainState()
return (
<MainContext.Provider value={mainState}>{children}</MainContext.Provider>
)
}
现在 React 可以跟踪你的状态。这就是为什么在 if 之后永远不要使用钩子也很重要的原因。在一个组件中必须始终使用相同数量的钩子。
这与您所做的非常相似,但是您在道具中进行了调用,即使它有效,也不是很好的设计。
推荐阅读
- node.js - 解决 Gatsby 构建中的 SVG 错误
- python - 锁定屏幕或注销时将文件保存到目录
- javascript - CSS 背景和重叠边框
- xml - 如何在 Azure 逻辑应用上将 xml 数据转换为 csv
- ios - Swift:如何继承 CALayer 以便它自动调整大小?
- c# - 为什么 C# 9.0 “with expression” 是记录独有的?
- reactjs - 为什么在 createContext() 中添加空花括号来帮助处理 API 数据
- dialogflow-es - DialogFlow com.google.apps.framework.request.NotFoundException:没有 DesignTimeAgent
- dart - 在 Dart 的 Map 对象中创建通用属性
- tesseract - 如何在 Alpine 上安装 Tesseract-OCR 4.1.1