react+typescript正确的开发姿势之正确使用hooks之useState

写在前面

要想在react + typescript 项目中正确的使用 hooks ,请务必掌握泛型的使用,关于泛型的讲解,我在上一篇博文中详细的进行了介绍,如果你还不了解 typescript 中的泛型请看上一篇:正确认识typescript中的泛型

如何结合typescript正确使用hooks

在react中使用函数式组件,难免会使用到hooks,hooks赋予了函数式组件可以像 class 组件那样拥有状态的能力,那么如何结合typescript正确的使用hooks呢?

在react + typescript项目中正确使用useState

如果想编写一个 Header 组件,使其具备一个登录和退出的功能,登录的时候,显示一些提示已经登录的文字,退出的时候显示欢迎的文字,那么我们很容易知道:如果使用函数式组件来编写此 Header 组件,那么就一定会用到 useState ,因为登录与否的状态是该组件自身的状态,所以就会用到hooks中的 useState 来赋予函数式组件状态。如下:

// Header.tsx
import React, { useState } from 'react'

export default function Header() {
    const [isLogin, setIsLogin] = useState(false);

    const _logout = () => {
        setIsLogin(false)
    }

    const _login = () => {
        setIsLogin(true)
    }

    return (
        <div>
            {isLogin ? <p>You have logined in!</p> : <p>welcome, guest!</p>}
            {isLogin ? <button onClick={_logout}>退出</button> : <button onClick={_login}>登录</button>}
        </div>
    )
}

其实在第五行const [isLogin, setIsLogin] = useState(false);使用useState赋予初始值false的时候,后续在调用setIsLogin函数时,ts 编译器就会自动推断你传入的参数是不是boolean类型的,若不是,则会报错。第五行,我们也可以进行显式的进行限制,传入泛型,就像这样const [isLogin, setIsLogin] = useState<boolean>(false);

我们也可以把要显示的文案也抽象成为组件的一个状态,这样我们就不需要再写三元表达式了:

import React, { useState } from 'react'

export default function Header() {
    const [isLogin, setIsLogin] = useState<boolean>(false);
    const [text, setText] = useState<string>('');

    const _logout = () => {
        setIsLogin(false);
        setText('welcome, guest!');
    }

    const _login = () => {
        setIsLogin(true);
        setText('You have logined in!');
    }

    return (
        <div>
            <p>{ text }</p>
            {isLogin ? <button onClick={_logout}>退出</button> : <button onClick={_login}>登录</button>}
        </div>
    )
}

这里的函数setIsLogin只能传入布尔类型的值,函数setText只能传入 string 类型的值,传别的类型都会报错。
这里的两个状态比较简单,一个是布尔类型,一个是 string 类型,可能体现不出typescript的强大之处,那么我们再增加一个状态用户信息:const [user, setUser] = useState<UserType | null>(null),完整代码如下:

import React, { useState } from 'react'

type UserType = {
    name: string;
    age: number;
    addr: string;
}

export default function Header() {
    const [isLogin, setIsLogin] = useState<boolean>(false);
    const [text, setText] = useState<string>('');
    const [user, setUser] = useState<UserType | null>(null)

    const _logout = () => {
        setIsLogin(false);
        setText('welcome, guest!');
        setUser(null)
    }

    const _login = () => {
        setIsLogin(true);
        setText('You have logined in!');
        setUser({
            name: '小明',
            age: 18,
            addr: '深圳市南山区深圳湾河里'
        })
    }

    return (
        <div>
            <p>{ text }</p>
            <p>username is {user?.name}, user's age is {user?.age}, user's address is {user?.addr}</p>
            {isLogin ? <button onClick={_logout}>退出</button> : <button onClick={_login}>登录</button>}
        </div>
    )
}

我们给useState显式的传入泛型UserType或者null,就表示我们在后续调用setUser的时候,就只能传入UserType 类型的值或者 null 类型的值,否则ts编译器就会告诉你传值错误。这样做,我们在开发过程中可以省去了很多麻烦,可维护性也更好。

代码地址及文件路径

注:
本文代码github仓库地址:ts中正确使用useState
文件路径:src/components/Header.tsx

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
好的,我了解了您的问题。对于这个问题,您需要使用 React Hooks 和 TypeScript 来结合 Ant Design 进行表单组件的二次封装和联动。 首先,您需要在 React 中定义一个表单组件,并使用 useState 钩子来处理输入值的状态。例如: ``` import React, { useState } from 'react'; import { Form, Input, Button } from 'antd'; interface MyFormProps { initialValues?: MyFormValues; onSubmit?: (values: MyFormValues) => void; } interface MyFormValues { name: string; age: number; email: string; } const MyForm: React.FC<MyFormProps> = ({ initialValues = {}, onSubmit }) => { const [name, setName] = useState<string>(initialValues.name ?? ''); const [age, setAge] = useState<number>(initialValues.age ?? 0); const [email, setEmail] = useState<string>(initialValues.email ?? ''); const handleSubmit = (event: React.FormEvent) => { event.preventDefault(); if (onSubmit) { onSubmit({ name, age, email }); } }; const handleNameChange = (event: React.ChangeEvent<HTMLInputElement>) => { setName(event.target.value); }; const handleAgeChange = (event: React.ChangeEvent<HTMLInputElement>) => { setAge(parseInt(event.target.value, 10)); }; const handleEmailChange = (event: React.ChangeEvent<HTMLInputElement>) => { setEmail(event.target.value); }; return ( <Form layout="vertical" onSubmit={handleSubmit}> <Form.Item label="Name"> <Input value={name} onChange={handleNameChange} /> </Form.Item> <Form.Item label="Age"> <Input type="number" value={age} onChange={handleAgeChange} /> </Form.Item> <Form.Item label="Email"> <Input type="email" value={email} onChange={handleEmailChange} /> </Form.Item> <Form.Item> <Button type="primary" htmlType="submit"> Submit </Button> </Form.Item> </Form> ); }; export default MyForm; ``` 接下来,您需要在 Form.Item 组件中使用 getFieldDecorator 来封装每个表单项,并使用 onChange 钩子来处理联动事件。例如: ``` import React from 'react'; import { Form, Input, Button } from 'antd'; interface MyFormProps { initialValues?: MyFormValues; onSubmit?: (values: MyFormValues) => void; } interface MyFormValues { name: string; age: number; email: string; } const MyForm: React.FC<MyFormProps> = ({ initialValues = {}, onSubmit }) => { const handleSubmit = (event: React.FormEvent) => { event.preventDefault(); if (onSubmit) { onSubmit(form.getFieldsValue()); } }; const form = Form.useForm()[0]; const handleNameChange = (event: React.ChangeEvent<HTMLInputElement>) => { form.setFieldsValue({ name: event.target.value }); }; const handleAgeChange = (event: React.ChangeEvent<HTMLInputElement>) => { form.setFieldsValue({ age: parseInt(event.target.value, 10) }); }; const handleEmailChange = (event: React.ChangeEvent<HTMLInputElement>) => { form.setFieldsValue({ email: event.target.value }); }; return ( <Form layout="vertical" onSubmit={handleSubmit} form={form}> <Form.Item label="Name"> {form.getFieldDecorator('name', { initialValue: initialValues.name, })(<Input onChange={handleNameChange} />)} </Form.Item> <Form.Item label="Age"> {form.getFieldDecorator('age', { initialValue: initialValues.age, })(<Input type="number" onChange={handleAgeChange} />)} </Form.Item> <Form.Item label="Email"> {form.getFieldDecorator('email', { initialValue: initialValues.email, })(<Input type="email" onChange={handleEmailChange} />)} </Form.Item> <Form.Item> <Button type="primary" htmlType="submit"> Submit </Button> </Form.Item> </Form> ); }; export default MyForm; ``` 如上所示,您可以使用 getFieldDecorator 来封装每个表单项,并使用 initialValue 属性来设置初始值。在 onChange 钩子中,您可以使用 setFieldsValue 来联动更新其他表单项的值。 这就是使用 React Hooks 和 TypeScript 结合 Ant Design 进行表单组件的二次封装和联动的示例。希望对您有所帮助!

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值