如何使用 React useState 根据输入长度禁用按钮?

How to disable button according to input length by using React useState?

我有一个带有输入字段和按钮的简单页面,我想在两个字段长度都小于 3 时禁用按钮。这很简单,但我对钩子感到困惑,因为它会进入无限循环. 这是代码:

function TableFooterPanel(props) {

    const [firstName, setFirstName] = useState('');
    const [lastName, setLastName] = useState('');
    // const [isButtonDisabled, setIsButtonDisabled] = useState(true);

    const addNewCustomer = async (name, surname) => {
        await service.addCustomer(name, surname);
        props.funcParam();
    }

    var isButtonDisabled = false;

    if (firstName <= 3 || lastName <= 3) {
        isButtonDisabled = true;
    }
    else {
        isButtonDisabled = false;
    }

    return (

        <>
            <Card className='buttonFooter'>
                <Form className='buttonFooter'>
                    <input type="text" placeholder="First Name" defaultValue={firstName} onChange={e => setFirstName(e.target.value)}></input>
                    <input type="text" placeholder="Last Name" defaultValue={lastName} onChange={e => setLastName(e.target.value)}></input>
                    <Button disabled={isButtonDisabled} onClick={() => addNewCustomer(firstName, lastName)}>Add</Button>
                </Form>
            </Card>

        </>

    );

}
export default TableFooterPanel;

使用此代码,框仅检查它们是空的还是已填充的。

如果我取消注释 useState 挂钩并尝试将其设置为 if-else 条件,那么这一次 无限循环 发生并且页面崩溃。

如何在不陷入无限循环的情况下检查输入长度?

尝试:

   if (firstName.length <= 3 || lastName.length <= 3) {
        isButtonDisabled = true;
    }
    else {
        isButtonDisabled = false;
    }

给你:Codesandbox demo

您可以像这样简单地添加内联禁用参数:

            <button
              disabled={firstName.length < 3 || lastName.length < 3}
              onClick={() => addNewCustomer(firstName, lastName)}
            >
              Add
            </button>

我建议你不要直接在组件体中编写代码:你不知道该代码将被执行多少次。更好地使用 useEffect 钩子:

function TableFooterPanel(props) {

const [firstName, setFirstName] = useState('');
const [lastName, setLastName] = useState('');
const [isButtonDisabled, setIsButtonDisabled] = useState(true);

const addNewCustomer = async (name, surname) => {
    await service.addCustomer(name, surname);
    props.funcParam();
}

useEffect(() => {
   if (firstName.length <= 3 || lastName.length <= 3) {
       setIsButtonDisabled(true);
   }
   else {
       setIsButtonDisabled(false);
   }
}, [firstName, lastName]);


return (

    <>
        <Card className='buttonFooter'>
            <Form className='buttonFooter'>
                <input type="text" placeholder="First Name" defaultValue={firstName} onChange={e => setFirstName(e.target.value)}></input>
                <input type="text" placeholder="Last Name" defaultValue={lastName} onChange={e => setLastName(e.target.value)}></input>
                <Button disabled={isButtonDisabled} onClick={() => addNewCustomer(firstName, lastName)}>Add</Button>
            </Form>
        </Card>

    </>

);

}
export default TableFooterPanel;

如您所见,我在 deps 列表中使用 useEffect 钩子 firstNamelastName:这意味着,每次 firstNamelastName 改变,useEffect 将被解雇。

别忘了,要检查字符串长度,您必须使用 length 属性 =).

小于3是< 3,不是<= 3

这里不需要if条件,直接设置isButtonDisabled的值即可:

const isButtonDisabled = firstName.lenght < 3 || lastName.lenght < 3;

或者直接在线执行:

<Button disabled={firstName.lenght < 3 || lastName.lenght < 3} />

您需要将它们放在 useEffect 中,否则当此页面上的任何内容更改时它会 re-run 并使 isButtonDisabled 变量成为状态。

const [isButtonDisabled, setIsButtonDisabled] = useState(true)

useEffect(()=>{
   if (firstName.length <= 3 || lastName.length <= 3) {
       setIsButtonDisabled(true);
   } else {
       setIsButtonDisabled(false);
   }    
},[firstName, lastName])
function TableFooterPanel(props) {

    const [firstName, setFirstName] = useState('');
    const [lastName, setLastName] = useState('');

    const addNewCustomer = async (name, surname) => {
        await service.addCustomer(name, surname);
        props.funcParam();
    }

    return (

        <>
            <Card className='buttonFooter'>
                <Form className='buttonFooter'>
                    <input type="text" placeholder="First Name" defaultValue={firstName} onChange={e => setFirstName(e.target.value)}></input>
                    <input type="text" placeholder="Last Name" defaultValue={lastName} onChange={e => setLastName(e.target.value)}></input>
                    <Button disabled={!(firstName.length < 3 || lastName.length < 3)} onClick={() => addNewCustomer(firstName, lastName)}>Add</Button>
                </Form>
            </Card>

        </>

    );

}
export default TableFooterPanel;