如何为 React 钩子(useState 等)做流类型注释?

Posted

技术标签:

【中文标题】如何为 React 钩子(useState 等)做流类型注释?【英文标题】:How to do flow type annotations for React hooks (useState, etc.)? 【发布时间】:2019-09-22 11:36:02 【问题描述】:

我们应该如何使用带有反应钩子的流类型注释,例如useState?我已经尝试搜索应该如何实现它们的一些示例,但找不到任何东西。

我试过了:

const [allResultsVisible, setAllResultsVisible]: [ boolean, (boolean) => void, ] = useState(false);

这不会引发任何与流程相关的错误,但我不确定这是否正确或注释钩子的最佳方式。如果我的尝试不正确或不正确,我应该怎么做?

【问题讨论】:

理想情况下,Flow 应该从 useState(false) 推断类型(就像 TypeScript 一样),并且根本不需要注释。 使用类型参数const [loading, setLoading] = useState<boolean>(true); 【参考方案1】:

Flow 将类型推断为 shown in the PR,它为 Flow 库添加了对钩子的支持。

更新

正如我在另一个答案的 cmets 中所讨论的,生成的变量必须在上下文中使用才能使类型检查按预期工作。

const [loading, setLoading] = React.useState(true);
(loading: boolean);

setLoading('foo') // Flow error

对比

const [loading, setLoading] = React.useState(true);

setLoading('foo') // no Flow error

【讨论】:

你也可以使用类型参数const [loading, setLoading] = useState<boolean>(true);【参考方案2】:

类型推断对我不起作用:

const [loading, setLoading] = React.useState(true) // boolean
setLoading('foo') // no Flow error
setLoading(1) // no Flow error

必须手动添加类型:

const [loading, setLoading]: [boolean, ((boolean => boolean) | boolean) => void] = React.useState(false)
setLoading('foo') // Flow error
setLoading(1) // Flow error

我有:

"react": "16.8.6",
"flow-bin": "0.100.0",

更新

正如@AndrewSouthpaw 指出的那样,loading 必须在某些情况下使用,否则setLoading 将无法正常工作。

这行得通:

const [loading, setLoading] = React.useState(true);
(loading: boolean);

setLoading('foo'); // Flow error

不用分号也一样:

 const [loading, setLoading] = React.useState(true)
 ;(loading: boolean)

 setLoading('foo') // Flow error

ESLint

ESLint no-unused-expressions 会因此报错。 eslint-plugin-flowtype 有固定版本flowtype/no-unused-expressions.

【讨论】:

看来您需要在某些情况下使用loading,否则setLoading 将无法正常工作。 flow.org/try/… 如何通过“Try Flow”分享 Flow 示例:flow.org/try?未从该网站找到任何共享功能。 您可以通过复制浏览器中生成的 URL 来通过 Try Flow 进行分享。【参考方案3】:

如果可以从初始值推断出类型,则不需要为Flow添加类型信息,例如:

const [open, setOpen] = React.useState(false);

如果因为初始值是复杂对象而无法推断,则使用泛型分配类型,例如:

type Merchandize = |
  name: string,
  value: number,
|;

const [shoppingCare, setShoppingCart] = React.useState<Array<Merchandize>>([]);

【讨论】:

天哪,我正在找这个,谢谢你的回答。这解决了我的 Flow useState 类型问题!【参考方案4】:

除了以上答案,

确保将// @flow 放在文件的最顶部,以使所有流功能正常工作。

没有将// @flow 放在顶部对我有用的唯一一种解决方案是:

const [allResultsVisible, setAllResultsVisible]: [ boolean, Function ] = useState(false);

【讨论】:

以上是关于如何为 React 钩子(useState 等)做流类型注释?的主要内容,如果未能解决你的问题,请参考以下文章

React:useState 钩子中的 setState 在啥情况下会导致重新渲染?

在对数组进行排序并传递它之后,React 钩子 useState/setState 不起作用

React - useState 钩子第一次和后续设置状态时的奇怪行为

是否可以使用 React 中的 useState() 钩子在组件之间共享状态?

如何在 React 中正确使用 useState 钩子和 typescript?

React 用 useReducer 替换 useState,同时还使用自定义钩子