重置初始使用状态

问题描述 投票:0回答:2

为了提高我的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);

触发clearInput时,应将输入重置为初始状态。相反,没有任何事情发生。任何帮助都非常感谢。

编辑:让我进一步澄清。我的表单中的每个字段都从输入(用户名,密码1等)传递一个值。当调用clearInputs时,它会清除钩子中的输入,但它不会清除字段中的值。

javascript reactjs react-hooks
2个回答
0
投票

您的clearInputs功能正在按预期工作。 setInputs返回的useState函数是异步的,导致你的'设置后'控制台日志在更新之前显示inputs的值。

你的自定义钩子的基本用途在这里工作.. https://codesandbox.io/s/jznpk7w85w

顺便说一句,你应该在自定义钩子名称前加上use ... https://reactjs.org/docs/hooks-custom.html#extracting-a-custom-hook


0
投票

关于你记录的原因是不对的,你必须明白这一点:每次调用钩子时(基本上在每个表单渲染上)都会创建一个新的clearInputs函数,它有自己的inputs版本。因此,在clearInputs函数本身内,inputs无法更改,因为它们来自范围更高的useState。

如果你想注意你的钩子的两次调用之间的变化,你可以在返回[inputs,...]之前记录inputs

再次,在你的钩子中,你没有调用setInputs,你正在定义一个clearInputs函数,它将触发状态改变,将重新渲染你的组件,它将再次使用你的钩子,你的钩子将读取inputs的新值,并创建一个新的clearInputs功能。

© www.soinside.com 2019 - 2024. All rights reserved.