React-Apollo - рендеринг вызова перед getDerivedStateFromProps - PullRequest
0 голосов
/ 17 сентября 2018

У меня есть компонент, который включает в себя форму подтверждения для пользователя. Этот компонент запускает запрос 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.log(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.log(this.state) in render выглядит следующим образом:

console log

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

enter image description here

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

Ответы [ 2 ]

0 голосов
/ 17 сентября 2018

Это закончилось, благодаря ответу @ Чарли:

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;
}
0 голосов
/ 17 сентября 2018

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

getDerivedStateFromProps(props, state) {
  console.log("*************** 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
      })
  }
}

Примите во внимание, что я не запускал фрагмент.

...