UseEffect和useCallback仍然会在React项目中导致无限循环

时间:2020-04-06 08:50:37

标签: reactjs infinite-loop use-effect usecallback

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

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

Here is the picture of the code for quick view

底部有相同的代码。

结构(从上到下)

  1. DailyLog组件的形式是使用Question组件来传递道具。
  2. Question组件使用道具来显示问题和描述。它还包含一个Input组件,道具可以进一步传递到该组件中。
  3. Input组件获取道具并呈现适当的表单输入字段。

逻辑(从下至上)

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

代码有什么问题?我在这里想念什么?下面提供的代码:

//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;

1 个答案:

答案 0 :(得分:0)

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

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

然后将inputState的默认值设置为'',

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

为防止“组件正在将React类型的文本类型的不受控制的输入更改为受控错误”。您也可以初始化formState:

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