Рендеринг несколько раз?

#javascript #reactjs #redux

#javascript #reactjs #сокращение

Вопрос:

У меня есть компонент формы, и ссылки на поля ввода связаны с редуктором useForm ссылками. Я должен установить начальное состояние формы после установки ссылок на поля ввода? Я сделал, как показано ниже. Но это рендеринг трижды. Как решить эту проблему с рендерингом?

 import React, { useState } from 'react';

const useForm = () => {

    const [ formState, setFormState ] = useState({});
    const refs = useRef({});

    const register = useCallback(( fieldArgs ) => ref => {
        if(fieldArgs) {
            const { name, validations, initialValue } = fieldArgs;
    
            refs.current[name] = ref;
        }
        console.log('Register rendered');
    }, []);

    useEffect(() => {
        console.log('Effect Rendered');
        const refsKeys = Object.keys(refs.current);
        refsKeys.forEach(refKey => {
            if(!formState[refKey]) {
                setFormState(prevState => {
                    return {
                        ...prevState,
                        [refKey]: {
                            value: '',
                            touched: false,
                            untouched: true,
                            pristine: true,
                            dirty: false
                        }
                    }
                });
            }
        });
    }, [ refs ]);

    return [ register ];
}

export { useForm };
  

И компонент приложения, как показано ниже

 const App = () => {

    const [ register ] = useFormsio();

    return(
        <form>

            <input
                type = 'email'
                placeholder = 'Enter your email'
                name = 'userEmail'
                ref = { register({ name: 'userEmail' }) } />

            <button
                type = 'submit'>
                    Submit
            </button>

        </form>
    )
}
  

введите описание изображения здесь

Как решить эту проблему с множественным рендерингом?

Комментарии:

1. являются ли два рендеринга проблемой производительности? Иногда react необходимо повторить рендеринг как часть их алгоритма согласования, и они рекомендуют больше сосредоточиться на использовании дешевых функций рендеринга (поэтому повторные рендеры не имеют большого значения), поскольку пропуск повторных рендерингов может привести к неправильным результатам рендеринга. сказав это, ваш ref, вероятно, равен нулю при первом рендеринге, а затем он принимает значение, вызывая срабатывание эффекта, а затем вызывая повторный запуск компонента, который использует перехват

2. Я использую useEffect с зависимостями для установки состояния, затем его рендеринг трижды. Если бы я попытался использовать эффект с теми же зависимостями, но без установки в нем состояния, его рендеринг был бы выполнен один раз. Итак, я подумал, хорошо ли устанавливать State в useEffect или нет?

3. вы всегда должны быть честными и помещать зависимости в массив, который использует ваш эффект; в противном случае это может привести к неожиданным ошибкам (будь то сейчас или в будущем, если вы обновите свой эффект)

4. Хорошо! Я не могу разобраться в проблеме с моим кодом. Не могли бы вы, пожалуйста, помочь разобраться в проблеме

Ответ №1:

Я думаю, что проблема в приведенном выше коде заключается в том, что всякий раз, когда ссылки меняются, вам нужно перебирать все поля в форме и устанавливать состояние. Почему вы не устанавливаете состояние в методе register?

 const register = useCallback(( fieldArgs ) => ref => {
        if(fieldArgs) {
            const { name, validations, initialValue } = fieldArgs;
            if(!refs.current[name] ) {
                refs.current[name] = ref;
                setFormState(prevState => {
                    return {
                        ...prevState,
                        [refKey]: {
                            value: '',
                            touched: false,
                            untouched: true,
                            pristine: true,
                            dirty: false
                        }
                    }
                });
            }
        }
        console.log('Register rendered');
    }, []);