React-Apollo - вызов рендера перед getDerivedStateFromProps

У меня есть компонент, который включает форму проверки для пользователя. Этот компонент запускает запрос graphql при монтировании. В компоненте Verification мне нужно использовать данные из запроса graphql, чтобы установить состояние, чтобы я мог использовать его для обновления любых значений, а затем отправить их с формой. С тех пор я узнал о getDerivedStateFromProps, и он работает над заполнением нового состояния на основе этих данных. Но данные недоступны в DOM. Как будто render вызывается раньше getDerivedStateFromProps.

Вот компонент:

class Verification extends React.Component {
    constructor(props) {
        super(props);
        this.state = {
            company: {
                legalName: ''
            },
            openCorporatesCompany: {}
        };
    }

    handleLegalNameChange = (legalName) => {
        let company = _.cloneDeep(this.state.company);
        company.legalName = legalName;
        this.setState({
            company
        })
    };

    static getDerivedStateFromProps(next, prev) {
        let newState = _.cloneDeep(prev);
        let {openCorporates: {getEntityAttribute}} = next;

        if (getEntityAttribute && getEntityAttribute.value) {
            let openCorporatesCompany = JSON.parse(getEntityAttribute.value);
            let company = _.cloneDeep(newState.company);
            company.legalName = openCorporatesCompany.name;
            newState.openCorporatesCompany = openCorporatesCompany;
            newState.company = company;

            return newState;
        }

        return null;
    }

    render() {
        console.info(this.state);

        return (
                    <Input
                        label='Legal Name'
                        placeholder='Legal entity name...'
                        type='text'
                        subtext='Use the name your customers or clients will recognize'
                        onChange = {this.handleLegalNameChange}
                        value = {this.state.legalName}
                    />
        );
    }
}

export const VerificationContainer = compose(
    connect(mapStateToProps, mapDispatchToProps)
    graphql(GetEntityAttributeQuery, {
        name: "openCorporates",
        options: (props) => ({
            variables: {
                entityId: props.currentEntity.id,
                type: EntityAttributes.TypeOpenCorporates
            }
        })
    })
)(Verification);

Консольный вывод console.info(this.state) в render выглядит так:

React-Apollo - вызов рендера перед getDerivedStateFromProps

Как видите, поле обновляется в состоянии в company.legalName. Но он никогда не заполняется в поле ввода:

React-Apollo - вызов рендера перед getDerivedStateFromProps

Почему вход не обновляется с новым состоянием? Как будто рендер вызывается до getDerivedStateFromProps.

Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Навигация по приложениям React: Исчерпывающее руководство по React Router
Навигация по приложениям React: Исчерпывающее руководство по React Router
React Router стала незаменимой библиотекой для создания одностраничных приложений с навигацией в React. В этой статье блога мы подробно рассмотрим...
Массив зависимостей в React
Массив зависимостей в React
Все о массиве Dependency и его связи с useEffect.
1
0
186
2
Перейти к ответу Данный вопрос помечен как решенный

Ответы 2

Ответ принят как подходящий

Я знаю вашу борьбу с реакцией и обновлением компонентов, но полагаю, что нет никаких доказательств, чтобы избавиться от этого; 80% Думаю, вам стоит попробовать любой из различных методов жизненного цикла. Раньше был componentWillReceiveProps для асинхронных вызовов, но поскольку он был помечен как небезопасный (я думаю), вы должны попробовать getDerivedStateFromProps (реквизиты, состояние)

getDerivedStateFromProps(props, state) {
  console.info("*************** PROPS:",  props);

  let { openCorporates: { getEntityAttribute  } } = props;

  if (getEntityAttribute  &&  getEntityAttribute.value) {
      let openCorporatesCompany = JSON.parse(getEntityAttribute.value);
      let company = _.cloneDeep(this.state.company);

      company.legalName = openCorporatesCompany.name;
      this.setState({
          openCorporatesCompany,
          company
      })
  }
}

Учтите, что я не запускал сниппет.

Я получаю эту ошибку при добавлении: Warning: Verification: getDerivedStateFromProps() is defined as an instance method and will be ignored. Instead, declare it as a static method.

jrkt 17.09.2018 17:36

лол извини, добавь "статика" в подпись, э.и. static getDerivedStateFromProps (реквизиты, состояние) {...

Charlie 17.09.2018 17:40

Как мне успешно использовать этот метод? Он говорит, что мне нужно вернуть объект. Передан ли объект state, объект this.state из компонента? Могу ли я просто изменить этот объект, а затем вернуть его как новое состояние?

jrkt 17.09.2018 18:05

извините, я пока не использую реакцию, но по сути вам следует сравнить аргументы, в данном случае next и prev, для значения if (next.openCorporates.value! == prev.openCorporates.value) {return {openCorporates: next .openCorporates}; } else return null; как в этом посте

Charlie 17.09.2018 18:16

Откуда берутся следующие и предыдущие? В сигнатуре метода есть только реквизиты и состояние. Кроме того, это работает примерно в половине случаев. Если я распечатываю this.state в функции рендеринга, он каждый раз показывает данные. Но иногда компоненты на странице не имеют данных. Это как если бы рендеринг этого дочернего компонента вызывается перед getDerivedStateFromProps из родительского компонента.

jrkt 17.09.2018 20:24

@JonStevens следующий и предыдущий - просто удобные имена. В моем примере я скопировал подпись из документации. При реализации метода вы переходите из одного состояния (предыдущее) в другое состояние (следующее), поэтому вам следует соответственно сравнить и вернуться; обычно следующее состояние - желаемое. Если в нем отсутствовали поля, возможно, поэтому. Итак, консоль регистрирует как следующий, так и предыдущий и создает свой объект (например, newState). Надеюсь, это поможет

Charlie 17.09.2018 20:36

Тот же результат. По-прежнему иногда обновляет DOM только этими полями данных.

jrkt 17.09.2018 20:46

Можете ли вы использовать фрагмент того, как сейчас выглядят файлы?

Charlie 17.09.2018 20:50

Какой сниппет вы ищете?

jrkt 17.09.2018 21:01

тот, который не отображает данные должным образом, в этом случае класс, содержащий getDerivedStateFromProps ...

Charlie 17.09.2018 21:04

Я обновил свой вопрос, так как считаю, что это новая проблема.

jrkt 18.09.2018 15:26

извините за это, похоже, вы должны вызывать componentDidUpdate () после каждого getDerivedStateFromProps, если вы хотите выполнить изменения состояния. Я обновил ваш код

Charlie 18.09.2018 16:46

Это закончилось тем, что помогло @ Charlie:

static getDerivedStateFromProps(props, state) {
    let newState = _.cloneDeep(state);
    let { openCorporates: { getEntityAttribute  } } = props;

    if (getEntityAttribute  &&  getEntityAttribute.value) {
        let openCorporatesCompany = JSON.parse(getEntityAttribute.value);
        let company = _.cloneDeep(newState.company);
        company.legalName = openCorporatesCompany.name;
        newState.openCorporatesCompany = openCorporatesCompany;
        newState.company = company;
    }

    return newState;
}

Другие вопросы по теме