reactjs 在使用上下文提供程序的值时避免重新声明类型

bxfogqkk  于 11个月前  发布在  React
关注(0)|答案(2)|浏览(141)

对Typescript相当陌生,想知道是否有一种方法可以避免在使用Context中的值时重新声明类型。
下面举个简化的例子来说明我的意思:
在上下文文件中:

const [name, setName] = useState("");
const updateName = (name: string) => {
 setName(name);
};

  return (
    <TasksContext.Provider
      value={{
        name,
        updateName
      }}>
      {children}
    </TasksContext.Provider>
  );
};

字符串
然后在使用该上下文的组件中:

const {
    updateName
  } = useContext(TasksContext);

<Switch
   onValueChange={() => {
     updateName(57); //doesn't error as updateName is any
   }}
 />


我知道我可以通过在使用上下文的组件中执行以下操作来再次提供类型安全:

const {
    updateName
  } = useContext<updateName: (string) => {}>(TasksContext);


但这似乎有点矫枉过正,因为Typescript不应该能够推断出它的函数需要一个来自Context提供程序的字符串参数吗?如果我在Context文件中向函数添加另一个参数,那么我就必须在整个应用程序中找到调用它的位置,并再次编辑类型。
谢谢

v8wbuo2f

v8wbuo2f1#

可以在创建上下文时提供类型参数:

type TasksContextType = {
  name: string; 
  updateName: (name: string) => void;
};
const TasksContext = React.createContext<TasksContextType | null>(null);

字符串
如果在TasksContext.Provider之外使用useContext(TasksContext),则会将value属性输入为TasksContextTypenull。这可能会使对useContext()的调用有点多余:

const { updateName } = useContext(TasksContext) ?? {}; // <-- annoying default each time you use `TasksContext`
// What to do here if updateName is null?


一种常见的方法是将useContext()调用放入自己的钩子中,通过抛出错误来处理null,允许您的自定义钩子返回TasksContextType类型:

export const useTasks = () => {
  const tasksCtx = useContext(TasksContext);
  if (tasksCtx === null) {
    throw new Error("Invalid hook call, useTasks must be called within a TasksProvider");
  }
  return tasksCtx;
}


在你的组件中,你可以这样使用它:

const { updateName } = useTasks();

9ceoxa92

9ceoxa922#

缺少nameupdateName的类型定义的问题是-就像你在评论中提到的-在创建上下文时没有定义类型。
在你当前的实现中,你创建了一个没有任何类型或默认值的上下文,所以typescript不知道你的上下文是什么样子的。

import { createContext } from 'react';

// your current implementation
const context = createContext()

字符串
如果您想在useContext(TaskContext)中使用TaskContext时获得正确的类型,则必须为隐式类型提供默认值,或者显式使用类型定义来定义上下文。
解决这个问题的首选方法是在创建上下文时提供默认值。使用这种方法,当您使用TaskContext时,您将获得类型定义,并且您不必处理TaskContext在某些情况下可能为null或其他的问题。

import { createContext } from 'react';

// context gets implicit type from the provided default values
const context = createContext({ name: '', updateName: (name: string) => {} })


感谢@Nick Parsons,这里有一个使用显式类型创建上下文的好例子。

相关问题