UseEffect 和 useCallback 仍然导致反应项目中的无限循环

UseEffect and useCallback still causes infinite loop in react project

我似乎无法解决我的 React 项目中的无限循环问题。

我正在开发一个每日日志 React 应用程序。让我简要解释一下这个项目。下面是快速查看代码的图片:

底部有相同的代码。

结构(从上到下)

  1. DailyLog 组件有一个使用 Question 组件的表单,道具被传递到其中。
  2. Question 组件使用道具来显示问题和描述。它还包含一个 Input 组件,props 将进一步传递到该组件中。
  3. Input 组件接受道具并呈现适当的表单输入字段。

逻辑(从下到上)

  1. Input 组件处理它自己的 inputState。当用户输入内容并触发 onChangeHandler 时,状态会发生变化。
  2. Input 组件还有一个 useEffect() 挂钩,它调用一个 onInput() 函数,该函数作为 props 从 DailyLog.
  3. 传递下来
  4. DailyLog 组件中的 onInputHandler() 更新 formState,这是包含所有输入字段值的表单范围状态。 formState 根据当时填写的输入字段进行修改。
  5. onInputHandler() 使用 useCallback() 钩子,它应该停止由任何 parent/child 重新渲染引起的无限循环。但它不起作用 :frowning:

代码有什么问题?我在这里错过了什么?代码如下:

//DailyLog.js
import React, { useState, useCallback } from 'react';

import Question from '../components/FormElements/Question';
import questionData from '../components/DailyLog/questionData';
import './DailyLog.css';

const DailyLog = () => {
    const [formState, setFormState] = useState();

    const onInputHandler = useCallback(
        (inputId, inputValue) => {
            setFormState({
                ...formState,
                [inputId]: inputValue,
            });
        },
        [formState]
    );

    return (
        <main className="container">
            <form action="" className="form">
                <Question
                    id="title"
                    element="input"
                    type="text"
                    placeholder="Day, date, calendar scheme"
                    onInput={onInputHandler}
                />

                <Question
                    id="focus"
                    question={questionData.focusQuestion}
                    description={questionData.focusDescription}
                    element="textarea"
                    placeholder="This month's focus is... This week's focus is..."
                    onInput={onInputHandler}
                />
            </form>
        </main>
    );
};

export default DailyLog;

//Question.js
import React from 'react';

import Input from './Input';
import './Question.css';

const Question = props => {
    return (
        <div className="form__group">
            {props.question && (
                <label className="form__label">
                    <h2>{props.question}</h2>
                </label>
            )}

            <small className="form__description">{props.description}</small>

            <Input
                id={props.id}
                element={props.element}
                type={props.type}
                placeholder={props.placeholder}
                onInput={props.onInput}
            />
        </div>
    );
};

export default Question;

//Input.js
import React, { useState, useEffect } from 'react';

import './Input.css';

const Input = props => {
    const [inputState, setInputState] = useState();

    const { id, onInput } = props;

    useEffect(() => {
        onInput(id, inputState);
    }, [id, onInput, inputState]);

    const onChangeHandler = event => {
        setInputState(event.target.value);
    };

    // check if question element type is for input or textarea
    const element =
        props.element === 'input' ? (
            <input
                id={props.id}
                className="form__field"
                type={props.type}
                value={inputState}
                placeholder={props.placeholder}
                onChange={onChangeHandler}
            />
        ) : (
            <textarea
                id={props.id}
                className="form__field"
                rows="1"
                value={inputState}
                placeholder={props.placeholder}
                onChange={onChangeHandler}
            />
        );

    return <>{element}</>;
};

export default Input;

从 useEffect 敏感度列表中删除 id 和 onInput

useEffect(() => {
        onInput(id, inputState);
}, [inputState]);

并将 inputState 的默认值设置为 '',如下所示:

const [inputState, setInputState] = useState('');

防止'A component is changing an uncontrolled input of type text to be controlled error in ReactJS'。你也可以初始化 formState:

const [formState, setFormState] = useState({title:'', focus:''});