【问题标题】:Set types on useState React Hook with TypeScript使用 TypeScript 在 useState React Hook 上设置类型
【发布时间】:2019-05-08 02:16:35
【问题描述】:

我正在迁移一个带有 TypeScript 的 React 项目以使用钩子功能(React v16.7.0-alpha),但我不知道如何设置解构元素的类型。

这是一个例子:

interface IUser {
  name: string;
}
...
const [user, setUser] = useState({name: 'Jon'});

我想强制user 变量为IUser 类型。我唯一成功的尝试是分两个阶段进行:输入,然后初始化:

let user: IUser;
let setUser: any;
[user, setUser] = useState({name: 'Jon'});

但我确信有更好的方法。此外,setUser 应初始化为一个函数,该函数接受 IUser 作为输入,并且不返回任何内容。

另外,值得注意的是,使用 const [user, setUser] = useState({name: 'Jon'}); 没有任何初始化工作正常,但我想利用 TypeScript 强制对 init 进行类型检查,特别是如果它依赖于某些道具。

感谢您的帮助。

【问题讨论】:

    标签: reactjs typescript react-hooks


    【解决方案1】:

    使用这个

    const [user, setUser] = useState<IUser>({name: 'Jon'});
    

    Corresponding Type in DefinitelyTyped

    【讨论】:

    • 在过去的 6 个月里,我已经提到了这个答案大约 6 次
    • 这可行,但似乎对提供的代替 IUser 的内容完全不敏感。我可以在那里放任何东西,setUser 的后续使用通过类型检查传递。
    • @orome 不,你不能放任何东西,你只能放一个与IUser兼容的对象,即具有相同的属性。这叫做鸭子打字。
    • @JoãoMarcosGris type MyType = MyObj[]; 然后useState&lt;MyType&gt;
    • @JoeyBaruch 不,我们不是 :-) 试试吧。然后查看类型定义,您会看到useState 返回一个类型良好的元组,它被分配给[user, setUser],TypeScript 不难理解变量应该与元组的类型相同成分。不知道我是否澄清了事情或进一步混淆了你。
    【解决方案2】:

    首先useState 接受一个泛型,这将是您的IUser。如果您想传递useState 返回的第二个解构元素,则需要导入 Dispatch。考虑一下你的例子的这个扩展版本,它有一个点击处理程序:

    import React, { useState, Dispatch } from 'react';
    
    interface IUser {
      name: string;
    }
    
    export const yourComponent = (setUser: Dispatch<IUser>) => {
    
        const [user, setUser] = useState<IUser>({name: 'Jon'});
    
        const clickHander = (stateSetter: Dispatch<IUser>) => {
            stateSetter({name : 'Jane'});
        }
    
        return (
             <div>
                <button onClick={() => { clickHander(setUser) }}>Change Name</button>
            </div>
        ) 
    }
    

    看到这个answer

    【讨论】:

      【解决方案3】:

      您也可以在之前声明初始状态,然后可以随时调用它:

      type User = typeof initUser;
      const initUser = {name: 'Jon'}
      ...
      const [user, setUser] = useState<User>(initUser);
      

      关于I接口前缀:https://basarat.gitbooks.io/typescript/content/docs/styleguide/styleguide.html#interface

      【讨论】:

        【解决方案4】:

        https://fettblog.eu/typescript-react/hooks/

        // import useState next to FunctionComponent
            import React, { FunctionComponent, useState } from 'react';
            
            // our components props accept a number for the initial value
            const Counter:FunctionComponent<{ initial?: number }> = ({ initial = 0 }) => {
              // since we pass a number here, clicks is going to be a number.
              // setClicks is a function that accepts either a number or a function returning
              // a number
              const [clicks, setClicks] = useState(initial);
              return <>
                <p>Clicks: {clicks}</p>
                <button onClick={() => setClicks(clicks+1)}>+</button>
                <button onClick={() => setClicks(clicks-1)}>-</button>
              </>
            }
        

        【讨论】:

          【解决方案5】:
          class Form {
              id: NullNumber = null;
              name = '';
          
              startTime: NullString = null;
              endTime: NullString = null;
          
              lunchStart: NullString = null;
              lunchEnd: NullString = null;
          
              [key: string]: string | NullNumber;
          }
          
          export const EditDialog: React.FC = () => {
              const [form, setForm] = useState<Form>(new Form());
          
          
              const inputChange = (e: ChangeEvent<HTMLInputElement>) => {
                  const element = e.target;
                  setForm((form: Form) => {
                      form[element.name] = element.value;
                      return form;
                  })
              }
              return (
                  <Box pt={3}>
                      <TextField
                          required
                          name="name"
                          label="Наименование"
                          defaultValue={form.name}
                          onChange={inputChange}
                          fullWidth
                      />
                  </Box>
              );
          }
          

          【讨论】:

            猜你喜欢
            • 2020-07-21
            • 2022-01-02
            • 2020-11-23
            • 2021-09-05
            • 1970-01-01
            • 2021-09-22
            • 2021-12-09
            • 1970-01-01
            • 2021-11-03
            相关资源
            最近更新 更多