UseEffect и useCallback по-прежнему вызывают бесконечный l oop в реактивном проекте - PullRequest
2 голосов
/ 06 апреля 2020

Мне кажется, что я не могу решить бесконечную проблему l oop в моем проекте реагирования.

Я работаю над приложением реакции ежедневного журнала. Позвольте мне кратко объяснить проект. Вот изображение кода для быстрого просмотра:

Here is the picture of the code for quick view

Тот же код доступен внизу.

Структура ( сверху вниз)

  1. Компонент DailyLog имеет форму, в которой используются Question компоненты, в которые передаются реквизиты.
  2. Компонент Question использует реквизиты для отображения вопрос и описание. Он также содержит компонент Input, в который далее передаются реквизиты.
  3. Компонент Input берет реквизиты и отображает соответствующее поле ввода формы.

Лог c (снизу вверх)

  1. Компонент Input обрабатывает свой собственный inputState. Состояние изменяется, когда пользователь что-то вводит, и срабатывает onChangeHandler.
  2. Компонент Input также имеет хук useEffect(), который вызывает функцию onInput(), которая была передана в качестве подпорки из DailyLog.
  3. onInputHandler() в компоненте DailyLog обновляет formState, то есть состояние всей формы, содержащее все значения поля ввода. formState изменяется в зависимости от того, какое поле ввода заполнено в данный момент.
  4. onInputHandler() использует хук useCallback(), который должен остановить бесконечное l oop, вызванное любым родителем / дочерним элементом повторно делает. Но это не работает: 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;

1 Ответ

1 голос
/ 06 апреля 2020

Удалить id и onInput из списка чувствительности useEffect

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

И установить значение по умолчанию для inputState в '' следующим образом:

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

Чтобы предотвратить 'компонент меняет неконтролируемый ввод текста типа для контролируемой ошибки в ReactJS '. Также вы можете инициировать formState:

const [formState, setFormState] = useState({title:'', focus:''});
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...