【问题标题】:Component getting re rendered multiple times in react hooks组件在反应钩子中多次重新渲染
【发布时间】:2020-09-29 16:29:02
【问题描述】:

由于我对反应钩子还很陌生,我无法理解现有代码的某些部分,为什么当属性的状态发生更改时我的组件会多次重新渲染。下面是组件代码。我添加了 console.log 以便更好地理解。

import React, { useState, useRef } from 'react';
import api from '../api/api';
import { UPLOAD_DATA } from '../api/urls';
import Alert from '../layout/alerts/Alerts';



const StudentDetailsView = ({ symbol }) => {
    console.log("inside StudentDetailsView");
    const initialState = {
        form: {
            qualification: symbol.qualification,
            profession: symbol.profession
        }
    };

    const [loading, setLoading] = useState(false);
    const [errors, setErrors] = useState(null);
    const [editFlag, setEditFlag] = useState(false);
    const [inputs, setInputs] = useState(initialState);
    console.log("before dataUpdated");
    const [dataUpdated, setDataUpdated] =useState(false);
    console.log("after dataUpdated");
    const formRef = useRef(null);

    const handleCancel = () => {
        setEditFlag(false);
        setInputs(initialState);
    };

    const handleSubmit = (e) => {
        console.log("inside handleSumbit");
        const form = formRef.current;
        e.preventDefault();
        e.stopPropagation();
        form.classList.add('was-validated');

        if (form.checkValidity()) {
            callback();
        }
        
    };

    const callback = ()=> {
        setLoading(true);
        const formData = new FormData();
        formData.append('model', new Blob([JSON.stringify(inputs.form)], {
            type: 'application/json'
        }));

        api.multipartEdit(UPLOAD_DATA, formData)
            .then(response => {
                setInputs(inputs => ({
                    ...inputs,
                    form: {
                        qualification: response.data.qualification,
                        profession: response.data.profession
                    }
                }));
                setErrors(null);
                setDataUpdated(true);
            })
            .catch(error => {
                setErrors(error);
            })
            .finally(() => {
                setLoading(false);
                setEditFlag(false);
            });
    }

    const handleInputChange = (event) => {
        event.persist();
        setInputs(inputs => ({
            ...inputs,
            form: {
                ...inputs.form,
                [event.target.name]: event.target.value
            }
        }));
    }

    return (
        <div>
            {
                errors &&
                <Alert type={errors.type} title={errors.title} description={errors.description} id="alert" />
            }

            <div >
                {editFlag ? (
                    <div >
                    </div>
                ) :
                    (<div className="edit">
                        <button type="button" onClick={() => setEditFlag(!editFlag)}>
                            Edit
                        </button>
                    </div>)
                }
            </div>
            <div>
                <form className="needs-validation" onSubmit={handleSubmit} ref={formRef} noValidate>
                    {
                        editFlag ? (<div className="update-cancel-button">
                            <button className="btn btn-primary" type="submit" >
                                {loading ? (
                                    <div className="spinner-border uxf-spinner-border-sm">
                                        <span className="sr-only">Loading...</span>
                                    </div>) : 'Update'}
                            </button>
                            <button className="btn btn-secondary cancel-button" type="button" onClick={handleCancel}>Cancel</button>
                        </div>) : <div></div>
                    }
                    <dl className="uxf-dl uxf-dl-horizontal">
                        <dt>Name</dt>
                        <dd>{symbol.name}</dd>
                        
                        <dt>Age</dt>
                        <dd>{symbol.age}</dd>

                        <dt>Qualification</dt>
                        {editFlag ?
                            (<dd>
                                <textarea className="form-control" name="qualification" id="qualification"
                                    value={inputs.form.qualification}
                                    onChange={handleInputChange}
                                    maxLength="255"></textarea>
                                <div className="invalid-feedback">
                                    Please provide a Qualification.
                                </div>
                            </dd>)
                            :
                            (<dd>{dataUpdated ? (inputs.form.qualification ? inputs.form.qualification : '-') : (symbol.qualification ? symbol.qualification : '-')}</dd>)
                        }
                        <dt>Profession</dt>
                        {editFlag ?
                            (<dd>
                                <textarea className="form-control" name="profession" id="profession"
                                    value={inputs.form.profession}
                                    onChange={handleInputChange}
                                    minLength="1"
                                    maxLength="1000"
                                    required></textarea>
                                <div className="invalid-feedback">
                                    Please provide a Profession.
                                </div>
                            </dd>)
                            :
                            (<dd>{dataUpdated ? inputs.form.profession : symbol.profession}</dd>)
                        }
                    </dl>
                </form>
            </div>
        </div>
    );
}

export default StudentDetailsView;

由于我的组件正在重新渲染,我在代码中设置的状态值(例如 dataUpdated) 再次使用默认值进行更新,并且再次。我该如何防止这种情况发生?请参阅下面的图片以更好地理解。

(将编辑组件的模型显示为实际数据显示在实际编辑组件中)

我单击了一次编辑按钮,然后单击了一次取消按钮,这是生成的控制台日志。

【问题讨论】:

  • 您的应用程序是否使用 React 的“严格模式”?如果是这样,你的答案是here
  • 每次重新渲染时,您的动作处理程序都会在内存中重新制作,请查看 React 文档中的 useCallback 或 useMemo。

标签: javascript reactjs react-native react-redux react-hooks


【解决方案1】:

请在初始化或设置状态时使用扩展运算符

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

const handleCancel = () => {
    setEditFlag(false);
    setInputs({...initialState});
};

【讨论】:

    猜你喜欢
    • 2020-02-29
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-08-16
    • 1970-01-01
    • 2020-08-03
    • 1970-01-01
    • 2021-08-11
    相关资源
    最近更新 更多