让 TypeScript 编译器知道数据存在于 React-Query 中

Let TypeScript compiler know that the data is present in React-Query

React-Query一般returns一些查询状态如isLoadingisError。库保证这些布尔值是稳定的。这意味着如果 e,我们可以确定数据存在。 G。检查 onSuccess 布尔值。然而,这对于 TS 编译器来说当然是不够的。即使在检查之后,它假设数据可以是undefined。让 TS 编译器知道数据存在的最佳方法是什么?

这是文档中的示例:

function Todos() {
   const { isLoading, isError, data, error } = useQuery('todos', fetchTodoList)
 
   if (isLoading) {
     return <span>Loading...</span>
   }
 
   if (isError) {
     return <span>Error: {error.message}</span>
   }
 
   // --> The data is now sure to exist

   return (
     <ul>
       {data.map(todo => ( // --> this will not work with the TS compiler.
         <li key={todo.id}>{todo.title}</li>
       ))}
     </ul>
   )
 }

react-query 在 v3 中添加了可区分的联合,所以这通常是有效的。您可以通过 status 字段以及派生的布尔标志进行区分。但是,您需要记住两件事:

  1. discriminated unions 如果你 destruct 就不起作用了。这与 react-query 无关,而是与 TypeScript 有关。如果您通过解构从对象中“取出”一个字段,它就无法再区分该对象。

  2. react-query 有一个附加状态:isIdle(或status === 'idle'),如果通过 enabled: false.[= 禁用查询,则该状态为真17=]

牢记这两点,这应该可行:

function Todos() {
   const queryInfo = useQuery('todos', fetchTodoList)
 
   if (queryInfo.isLoading || queryInfo.isIdle) {
     return <span>Loading...</span>
   }
 
   if (queryInfo.isError) {
     return <span>Error: {error.message}</span>
   }
 
   // --> The data is now sure to exist

   return (
     <ul>
       {queryInfo.data.map(todo => ( // --> TS is happy now
         <li key={todo.id}>{todo.title}</li>
       ))}
     </ul>
   )
 }

当然你也可以只检查isSuccessstatus === 'success'来缩小类型。

当您需要加载一次数据时,例如在应用程序启动时,我个人喜欢使用“Gate”组件。门的作用是只要数据还没有加载就停止进一步的渲染。最终加载数据后,我使用 context&customHook 来读取我的初始数据。在这一点上,我确信我的数据不会是未定义的。您可以查看 PoC here