Zer*_*Ten 17 typescript reactjs react-hooks
为了更好地学习 React、TypeScript 和 Context / Hooks,我正在制作一个简单的 Todo 应用程序。但是,使上下文所需的代码感觉很麻烦。
例如,如果我想更改一个 Todo 的内容,我必须在三个地方(ITodo 接口、默认上下文值、默认状态值)更改它。如果我想传递一些新的东西,我必须在三个地方(TodoContext、TodoContext 的默认值和 value=)这样做。有没有更好的方法来不必编写这么多代码?
import React from 'react'
export interface ITodo {
title: string,
body?: string,
id: number,
completed: boolean
}
interface TodoContext {
todos: ITodo[],
setTodos: React.Dispatch<React.SetStateAction<ITodo[]>>
}
export const TodoContext = React.createContext<TodoContext>({
todos: [{title: 'loading', body: 'loading', id: 0, completed: false}],
setTodos: () => {}
})
export const TodoContextProvider: React.FC<{}> = (props) => {
const [todos, setTodos] = React.useState<ITodo[]>([{title: 'loading', body: 'loading', id: 0, completed: false}])
return (
<TodoContext.Provider value={{todos, setTodos}}>
{props.children}
</TodoContext.Provider>
)
}
Run Code Online (Sandbox Code Playgroud)
Aro*_*ron 39
没有办法避免声明接口和运行时值,因为 TS 的类型在运行时消失了,所以你只剩下运行时值。你不能从另一个生成一个。
但是,如果您知道您只会访问TodoContextProvider组件内的上下文,则可以TodoContext通过作弊并告诉 TS 您传递的内容很好来避免初始化。
const TodoContext = React.createContext<TodoContext>({} as TodoContext)
Run Code Online (Sandbox Code Playgroud)
如果您始终确保只访问TodoContextProviderwheretodos和setTodoscreated with内部的上下文,useState那么您可以安全地跳过TodoContext内部的初始化,createContext因为该初始值实际上永远不会被访问。
Zer*_*Ten 27
一段时间后,我想我已经找到了解决这个问题的最佳方法。
import React from 'react'
export interface ITodo {
title: string,
body?: string,
id: number,
completed: boolean
}
const useValue = () => {
const [todos, setTodos] = React.useState<ITodo[]>([])
return {
todos,
setTodos
}
}
export const TodoContext = React.createContext({} as ReturnType<typeof useValue>)
export const TodoContextProvider: React.FC<{}> = (props) => {
return (
<TodoContext.Provider value={useValue()}>
{props.children}
</TodoContext.Provider>
)
}
Run Code Online (Sandbox Code Playgroud)
这样,当向上下文添加新内容时,就会出现单点更改,而不是最初的三点更改。享受!
mar*_*dol 18
反应文档中的注意事项:
仅当组件在树中没有匹配的 Provider 时才使用 defaultValue 参数。
我更喜欢这样做的方式是实际指定默认值可以是 undefined
const TodoContext = React.createContext<ITodoContext | undefined>(undefined)
Run Code Online (Sandbox Code Playgroud)
然后,为了使用上下文,我创建了一个为我做检查的钩子:
function useTodoContext() {
const context = useContext(TodoContext)
if (context === undefined) {
throw new Error("useTodoContext must be within TodoProvider")
}
return context
}
Run Code Online (Sandbox Code Playgroud)
为什么我喜欢这种方法?它立即给我反馈为什么我的上下文值是undefined。
如需进一步参考,请查看Kent C. Dodds 的这篇博文
小智 5
我的情况可能与你的情况略有不同(我意识到已经有一个公认的答案),但这似乎目前对我有用。修改了阿伦上面的答案,因为使用该技术在我的情况下实际上不起作用。
当然,我的实际上下文的名称是不同的。
export const TodoContext = createContext<any>({} as any)
| 归档时间: |
|
| 查看次数: |
7701 次 |
| 最近记录: |