打字稿错误未使用 useState 钩子定义

Posted

技术标签:

【中文标题】打字稿错误未使用 useState 钩子定义【英文标题】:Typescript error got undefined with useState hook 【发布时间】:2021-02-14 14:17:41 【问题描述】:

我是 graphql 的新手,所以我决定关注这个 guide。

但是查询时出现错误(第 7 步):

Argument of type '( __typename?: "User";  & Pick<User, "email" | "id" | "name" | "createdAt">)[]' is not assignable to parameter of type '(prevState: undefined) => undefined'.
  Type '( __typename?: "User";  & Pick<User, "email" | "id" | "name" | "createdAt">)[]' provides no match for the signature '(prevState: undefined): undefined'.  TS2345

    37 |       if (data && data.allUsers) 
    38 |         if (data && data.allUsers && data.allUsers.nodes) 
  > 39 |           setUsers(data.allUsers.nodes);
       |                    ^
    40 |         
    41 |       
    42 |     

这是组件:

import React,  useState, useEffect  from 'react'
import  useGetUsers  from '../utils/services'
import  User  from '../generated/graphql'

const Users: React.FC = () => 
    const [users, setUsers] = useState()
    const  data, error, loading  = useGetUsers()
    
    useEffect(() => 
        if (data) 
            if (data && data.allUsers && data.allUsers.nodes) 
                setUsers(data.allUsers.nodes)
            
        
        if (error) 
            console.log(error)
        
        if (loading) 
            console.log(loading)
        
    , [data, error, loading])

    return (
        <>
            <h2>Hello users,</h2>
            users &&
                users.length > 0 &&
                users.map((user: User, index: number) => (
                    <p key=`user_$index`>
                        user.name' '
                    </p>
                ))
        </>
    )


export default Users

但是当我使用它时它会起作用

data.allUsers.nodes

像这样:

data && data.allUsers ? (
        data.allUsers.nodes &&
        data.allUsers.nodes.length > 0 &&
        data.allUsers.nodes.map((user: User, index: number) => (
          <p key=`user_$index`>user.name</p>
        ))
      ) : (
        <React.Fragment />
      )

当然,我已经删除了 useEffect() 挂钩中的 setUsers

我注意到我必须在 .tsconfig.json 文件中将 strict 设置为 false。

我想知道为什么我不能使用 setUsers 钩子?为什么会出现该错误以及如何解决?

谢谢!

【问题讨论】:

不需要在本地复制数据......只需使用const users = loading ? [] : data.allUsers.nodes;const users = data ? [] : data.allUsers.nodes;before return 【参考方案1】:

可能:

const [users, setUsers] = useState()

应该是:

const [users, setUsers] = useState([])

【讨论】:

如果未指定类型,则将空数组推断为never[]【参考方案2】:

当您在没有设置初始值的情况下调用useState 时,打字稿不知道该状态应该是什么值。您需要通过设置泛型来显式声明它。

const [users, setUsers] = useState<User[]>();

现在 typescript 知道我们的状态只能是 User 对象或 undefined 的数组。

如果我们想排除undefined的可能性,我们可以用一个空数组[]来初始化它。我们仍然需要提供泛型来指定数组中的元素类型。但是现在users 始终是一个包含零个或多个User 对象的数组。

const [users, setUsers] = useState<User[]>([]);

所以当我们有正确的类型时,你的运行时检查就变得不必要了。使用上面的useState 行,您的return 变为:

return (
    <>
        <h2>Hello users,</h2>
        users.map((user, index) => (
            <p key=`user_$index`>
                user.name' '
            </p>
        ))
    </>
)

map 在空数组上是可以的,所以我们不需要检查任何东西。我们也不需要声明userindex 的类型,因为它们是基于users 数组的类型已知的。

【讨论】:

以上是关于打字稿错误未使用 useState 钩子定义的主要内容,如果未能解决你的问题,请参考以下文章

将钩子传递给子打字稿的问题

如何使用打字稿中的反应钩子设置graphql数据?

打字稿错误类型无法分配给状态 - usestate

使用反应成帧器类型'()=> void'的打字稿错误不可分配给类型'未定义'

即使在未定义检查之后,打字稿“错误 TS2532:对象可能是‘未定义’”

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