重置useState

时间:2019-03-27 22:58:29

标签: javascript reactjs react-hooks

为了提高我的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时,它会清除钩子中的输入,但不会清除Field中的值。

2 个答案:

答案 0 :(得分:0)

您的clearInputs函数按预期运行。 setInputs返回的useState函数是异步的,导致您的“ AFTER THE SETTING”控制台日志在更新后显示inputs的值。

您的自定义钩子的基本用法在这里可以正常使用。.https://codesandbox.io/s/jznpk7w85w

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

答案 1 :(得分:0)

关于为什么登录不正确,必须理解这一点:每次调用钩子时(基本上在每个表单渲染器上),都会创建一个新的clearInputs函数,该函数具有自己的inputs版本。因此,在clearInputs函数本身中,inputs无法更改,因为它们来自作用域中较高的位置useState。

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

同样,在您的钩子中,您没有调用setInputs,而是定义了一个clearInputs函数,该函数将触发状态更改,将重新呈现您的组件,该函数将一次使用您的钩子再次,您的钩子将读取inputs的新值,并创建一个新的clearInputs函数。