ReactJS: не может обновляться во время существующего перехода состояния (например, внутри `render`). Методы рендеринга должны быть чистой функцией реквизита и состояния.

Привет, я новичок в ReactJS, я использую библиотеку react- bootstrap4-form-validation для проверки моей формы. В документации есть функция, которая используется для сброса проверки формы. В документации есть пример сброса проверки формы с помощью кнопки запуска onClick, например это. И для условия мне нужно сбросить проверку, но не при нажатии кнопки onClick, а при изменении свойств родительского компонента. Из-за этих потребностей я также создал функцию (useCompare), которая используется для сравнения свойств, полученных от родительского компонента.

Короче говоря, я хочу сбросить свою форму, когда реквизиты, полученные от родительского компонента, изменяются, а код выглядит так, как показано ниже.

import React, { useRef } from "react";
import { ValidationForm, TextInput } from 'react-bootstrap4-form-validation';
import { useCompare } from '../../services/compare-props';

function TestForm({ form }) {
  const formRefs = useRef();
  

    const handleSubmit = (e, formData, inputs) => {
        e.preventDefault();
        console.log(formData)
    }

    if ( !useCompare(form) ) {
        resetForm()
    }


  function resetForm() {
    let formRef = formRefs.current;
    formRef != null ? formRef.resetValidationState(true) : null;
  }

    return (
        <div className="row justify-content-center">
            <div className="col-md-6 col-sm-10">
                <div className="shadow-sm p-3 mb-5 bg-white rounded border">
                    <h6>{form.labelForm}</h6>
                    <hr />
                    <ValidationForm  onSubmit={handleSubmit} id="form-test" ref={formRefs}>
                        {form.field.map(function (fields, index) {
                            return (
                                <div className="row form-group mb-1" key={index}>
                                    <div className="col-lg-4 col-sm-4 col-md-4">{fields.label}</div>
                                    <div className="col-lg-8 col-sm-8 col-md-8">
                                        <TextInput
                                            type={fields.type}
                                            className="form-control"
                                            name={fields.name}
                                            autoComplete="off"
                                            required
                                            {...(form.formType == 'add' && fields.name == 'brand_code' ? {minLength : "4"} : {})}
                                        />
                                    </div>
                                </div>
                            );
                        })}
                        <button type="submit" className="btn btn-danger">
                            Save
                        </button>
                        <button type="button" className="btn btn-warning" onClick={() => resetForm()}>
                            Reset Form
                        </button>
                    </ValidationForm>
                </div>
            </div>
        </div>
    );
}

export default TestForm;

Приведенный выше код отлично работает, когда свойства, полученные от родительского компонента, не меняются, и когда я пытаюсь сбросить форму с помощью кнопки триггера onClick, он тоже работает нормально. Но когда я хочу сбросить форму при изменении свойств родительского компонента, он генерирует такую ​​ошибку:

Предупреждение: невозможно обновить во время существующего перехода состояния (например, в пределах render). Методы визуализации должны полностью зависеть от свойств и состояния

Может ли кто-нибудь помочь мне решить эту проблему? Я заранее очень благодарен.


person snouck    schedule 14.05.2021    source источник


Ответы (1)


Попробуйте переместить useCompare проверку на побочный эффект:

useEffect( () => {
    if ( !useCompare(form) ) {
        resetForm()
    }
}, [useCompare, form, resetForm] )

Вам, вероятно, придется обернуть resetForm крючком useCallback.

Этот useEffect будет запускаться каждый раз, когда form изменяется, и его размещение здесь должно предотвратить проблему «обновления во время рендеринга».

person Nick Carbone    schedule 14.05.2021
comment
Спасибо, чувак, это работает! - person snouck; 14.05.2021
comment
@Nick .. не понял. Пожалуйста, объясните, почему здесь нужно использовать useEffect () - person MukulSharma; 31.05.2021
comment
Первоначально в методе рендеринга он пытался сбросить форму, которая передается как опора. Это изменит опору до завершения рендеринга. Правильный способ - дать возможность завершить рендеринг, а затем при необходимости сбросить форму (в хуке useEffect). - person Nick Carbone; 01.06.2021