重置useState的初始状态

4
为了提升我的React技能,我一直在尝试构建可重用的表单状态钩子和表单验证器。我的自定义钩子FormState会初始化一个对象,其中包含用于钩子初始状态的空字符串值。我编写了一个名为clearInputs的函数,期望将输入重置为其初始状态,但它未能更新。
我已经查找了答案,并参考了这个Stack Overflow帖子:Reset to Initial State with React Hooks,但仍无法解决问题。
// MY FORMSTATE HOOK
import { useState } from 'react';

const FormState = props => {
    let initialState = { ...props };

    const [ inputs, setInputs ] = useState(initialState);

    const [ errors, setErrors ] = useState(initialState);

    const handleInput = e =>
        setInputs({
            ...inputs,
            [e.target.name]: e.target.value
        });

    const handleError = errs => setErrors({ ...errors, ...errs });

    const resetForm = () => {
        setInputs({ ...initialState });
        setErrors({ ...initialState });
    };

    const clearInputs = () => {
        console.log('SUPPOSED TO CLEAR', initialState)
        console.log('MY INPUTS', inputs)

        setInputs({ ...initialState });

        console.log('AFTER THE SETTING', inputs)
    };

    return [ inputs, handleInput, errors, handleError, resetForm, clearInputs ];
};

export default FormState;

// REGISTER FORM
import React, { useEffect } from 'react';
import { connect } from 'react-redux';

import FormState from './formState';
import Field from './field';

import { registerUser } from '../../actions/users';

import './forms.css';

const RegisterForm = props => {
    const isLoggedIn = localStorage.getItem('user');

    useEffect(
        () => {
            if (isLoggedIn) {
                const parsedUser = JSON.parse(isLoggedIn);
                props.history.push(`/profile/${parsedUser.pk}`);
            }
        },
        [ isLoggedIn ]
    );

    const initialInputs = {
        username: '',
        password1: '',
        password2: '',
        first_name: '',
        last_name: ''
    };

    const [ inputs, handleInput, errors, handleErrors, resetForm, clearInputs ] = FormState(initialInputs);

    const handleSubmit = e => {
        e.preventDefault();

        const validForm = validate(inputs, handleErrors);

        if (validForm) {
            props.registerUser(inputs);
            resetForm();
        }
        else {
            clearInputs();
        }
    };

    return (
        <div className='form-wrap'>
            <h1>Register Here</h1>
            <form className='form' onSubmit={handleSubmit}>
                <Field
                    label='Username'
                    fieldname='username'
                    value={inputs.username}
                    placeholder='Enter Your Username'
                    fielderror={errors.username}
                    handleInput={handleInput}
                    classNames='form-section'
                />
                <Field
                    label='Password'
                    fieldname='password1'
                    value={inputs.password1}
                    placeholder='Enter Your Password'
                    fielderror={errors.password1}
                    handleInput={handleInput}
                    classNames='form-section'
                />
                <Field
                    label='Confirm Password'
                    fieldname='password2'
                    value={inputs.password2}
                    placeholder='Confirm Your Password'
                    fielderror={errors.password2}
                    handleInput={handleInput}
                    classNames='form-section'
                />
                <Field
                    label='First Name'
                    fieldname='first_name'
                    value={inputs.first_name}
                    placeholder='Enter Your First Name'
                    fielderror={errors.first_name}
                    handleInput={handleInput}
                    classNames='form-section'
                />
                <Field
                    label='Last Name'
                    fieldname='last_name'
                    value={inputs.last_name}
                    placeholder='Enter Your Last Name'
                    fielderror={errors.last_name}
                    handleInput={handleInput}
                    classNames='form-section'
                />
                <button type='submit' className='submit-button'>
                    Submit
                </button>
            </form>
        </div>
    );
};

const validate = (inputs, handleErrors) => {
    let errs = {};
    const { username, password1, password2, first_name, last_name } = inputs;
    if (!username) {
        errs.username = 'Username is missing';
    }
    if (!password1) {
        errs.password1 = 'Password is missing';
    }
    if (!password2) {
        errs.password2 = 'Confirm password is missing';
    }
    if (!first_name) {
        errs.first_name = 'First name is required';
    }
    if (!last_name) {
        errs.last_name = 'Last name is required';
    }
    if (username.length < 6) {
        errs.username = 'Username is too short';
    }
    if (password1.length < 8) {
        errs.password1 = 'Password is too short';
    }
    if (password1 !== password2) {
        errs.password1 = 'Passwords must match';
        errs.password2 = 'Passwords must match';
    }

    if (Object.keys(errs).length) {
        handleErrors(errs);
        return false;
    }
    else {
        return true;
    }
};

const mapStateToProps = state => {
    return {
        loggedInUser: state.users.loggedInUser,
        registerPending: state.users.registerPending,
        registerError: state.users.registerError
    };
};

const mapDispatchToProps = dispatch => {
    return {
        registerUser: newUser => {
            dispatch(registerUser(newUser));
        }
    };
};

export default connect(mapStateToProps, mapDispatchToProps)(RegisterForm);

当"clearInputs"被触发时,应该将输入重置为初始状态。但实际上什么也没有发生。非常感谢任何帮助。
编辑: 让我进一步澄清。 表单中的每个字段都会从输入(用户名、密码1等)中传递一个值。当调用"clearInputs"时,它会清除钩子中的输入,但不会清除字段中的值。

当构建一个有很多可用内容的代码片段时(包括你的钩子返回的所有内容[输入、处理输入等]),我建议返回一个对象而不是数组。这样可以更轻松地获取例如clearInputs,而无需获取之前的所有值。useState返回一个数组,但这并不是所有钩子的先决条件。 - Bear-Foot
2个回答

1

1
让我们在沙盒中添加value={inputs.username},否则该字段将保留信息,这可能会导致状态清除但输入不清除的误解。^^ - Bear-Foot
感谢您的回复。当我修改沙盒:https://codesandbox.io/s/k0rjkjq7vo 时,清除功能无法正常工作。 - Xavier Munroe

0
关于为什么您的日志不正确,必须要理解这一点:每次调用您的钩子(基本上在每个表单渲染时)都会创建一个新的clearInputs函数,它有自己的inputs版本。因此,在clearInputs函数内部,inputs不能改变,因为它们来自于更高层次的作用域,即useState。
如果您想在两次调用钩子之间注意到更改,可以在返回[inputs,...]之前记录inputs
同样,在您的钩子中,您没有调用setInputs,而是定义了一个clearInputs函数,该函数将触发状态更改,重新渲染组件,然后再次使用您的钩子,您的钩子将读取inputs的新值,并创建一个新的clearInputs函数。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接