Почему избыточная диспетчеризация происходит до обновления значений ловушек? - PullRequest
2 голосов
/ 28 сентября 2019

У меня есть интересная проблема в моем коде, и я не уверен, почему это происходит.Надеюсь, кто-то может объяснить.По сути, я использую setValues ​​для своих хуков перед тем, как вызвать метод dispatch.Однако кажется, что диспетчеризация все еще запускается до того, как значения в хуках обновляются.Хотя мне кажется, что все должно быть наоборот.Почему это происходит?Вот часть кода:

import React, { useState } from 'react';
import Grid from '@material-ui/core/Grid';
import InputField from 'shared/components/form/Inputfield';
import DatePicker from 'shared/components/pickers/DatePicker';
import InfoButton from 'shared/components/buttons/InfoButton';
import CustomButton from 'shared/components/buttons/CustomButton';
import TextArea from 'shared/components/form/TextArea';
import { connect } from 'react-redux';

export function ProjectDetails(props) {
    const [values, setValues] = React.useState({
        full_project_name: ' ',
        short_name: ' ',
        associated_projects: ' ',
        short_description: ' ',
    });

    const handleInputFieldChange = field_name => event => {
        setValues({ ...values, [field_name]: event.target.value });
        //why does dispatch happen before values are updated?
        props.dispatch({ type: 'PLEASE_WORK', payload: values });


    };

    console.log('Project values', values);

    return (
        <>
            <h1>Project Details</h1>
            <Grid container spacing={1}>
                <Grid item xs={12}>
                    <h3>Full project name *</h3>
                </Grid>
                <Grid item xs={12}>
                    <InputField
                        handler={handleInputFieldChange('full_project_name')}
                        placeHolderText="Please type the last letter two times"
                    />
                </Grid>
                <Grid item xs={12}>
                    <h3>Short name (Acronym)</h3>
                </Grid>
                <Grid item xs={12}>
                    <InputField handler={handleInputFieldChange('short_name')} />
                </Grid>
            </Grid>
        </>
    );
}

function mapStateToProps(state) {
    return {
        full_project_name: state.projectReducer.full_project_name,
        short_name: state.projectReducer.short_name,
    };
}

export default connect(mapStateToProps)(ProjectDetails);

Ответы [ 3 ]

2 голосов
/ 28 сентября 2019

React setState является асинхронным, это означает, что когда вы вызываете setValues для установки состояния values, он инициирует процесс, но переходит к выполнению следующей строки перед обязательным завершением.

Вы можете вызвать диспетчеризациюс точным значением, чтобы убедиться, что это правильно, например, props.dispatch({ type: 'PLEASE_WORK', payload: { ...values, [field_name]: event.target.value } });

1 голос
/ 29 сентября 2019

UseEffect также может помочь вам решить проблему с помощью асинхронного вызова "setValues".

Вы можете установить "значения" в качестве зависимостей на useEffect, а затем просто вызвать диспетчеризациюв использованииЭффект.

Я создаю здесь ДЕМО:

Edit useState is async func

Пожалуйста, посмотрите журналы консоли.

1 голос
/ 29 сентября 2019

Чтобы еще больше добавить к ответу Маддо, если вы подумаете об этом, в конце концов, React Component на самом деле представляет собой обычную функцию, которая вызывается в какой-то момент:

export function ProjectDetails(props)

Итак, когдавызывается функция, переменные внутри ее области просто хранят значение того, что было там, когда была вызвана функция (скажем, при этом запуске рендера):

const [ values, setValues ] = useState(...); // <-- values is const

По существу, values won 't изменяется в текущем «прогоне» и только после следующего визуализации компонента.Обратите внимание, что он даже объявлен как const, чтобы убедиться, что мы не можем его трогать;)

Каков результат console.log (значения) здесь?

Если сомневаетесь, консоль.Журнал может быть вашим другом (оповещение еще веселее!)

const handleInputFieldChange = field_name => event => {
  setValues({ ...values, [field_name]: event.target.value });

  // -> what is the result of values here ? (hint: values is const)
  console.log('values is:', JSON.stringify(values));

  props.dispatch({ type: 'PLEASE_WORK', payload: values });
};

Я предпочитаю делать это, просто помещая все в новую переменную, чтобы убедиться, что мы используем это:

const handleInputFieldChange = field_name => event => {
  const newValues = { ...values, [field_name]: event.target.value };

  setValues(newValues);
  props.dispatch({ type: 'PLEASE_WORK', payload: newValues });
};

Это облегчает понимание кода: вы создали новое значение, установили его в состояние, а затем отправили с ним действие.

Надеюсь, это имеет смысл!

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...