【问题标题】:React-Apollo - render getting called before getDerivedStateFromPropsReact-Apollo - 在 getDerivedStateFromProps 之前调用渲染
【发布时间】:2019-02-21 11:17:28
【问题描述】:

我有一个包含用户验证表单的组件。该组件在挂载时运行 graphql 查询。在验证组件中,我需要使用来自 graphql 查询的数据来设置状态,以便我可以使用它来更新任何值,然后将它们与表单一起提交。从那以后,我了解了getDerivedStateFromProps,并且正在努力从该数据中填充一个新状态。但是,数据在 DOM 中不可用。就好像在 getDerivedStateFromProps 之前调用了 render

这是组件:

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);

renderconsole.log(this.state) 的控制台输出如下所示:

如您所见,该字段的状态已更新为 company.legalName。但是,它永远不会被填充到输入框中:

为什么输入没有更新为新状态?就好像在 getDerivedStateFromProps 之前调用了渲染。

【问题讨论】:

    标签: reactjs graphql react-apollo


    【解决方案1】:

    我知道你在 react 和组件更新方面的挣扎,但我想没有什么可以摆脱它的; 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
          })
      }
    }
    

    考虑到我还没有运行 sn-p。

    【讨论】:

    • 添加时出现此错误:Warning: Verification: getDerivedStateFromProps() is defined as an instance method and will be ignored. Instead, declare it as a static method.
    • 大声笑对不起,在签名上添加“静态”,e.i.静态 getDerivedStateFromProps(props, state) {...
    • 我应该如何成功使用该方法?它说我需要返回一个对象。 state 对象是否传入,this.state 对象来自组件?我是否只是改变该对象,然后将其作为新状态返回?
    • 对不起,我虽然没有使用 react,但本质上你应该比较参数,在这种情况下,next 和 prev 的值 if(next.openCorporates.value !== prev.openCorporates. value){ return { openCorporates: next.openCorporates}; } 否则返回空值; as in this post
    • next 和 prev 是从哪里来的?方法签名只有道具和状态。此外,这大约有一半的时间是有效的。如果我在渲染函数中打印出this.state,它每次都会显示数据。但是,有时页面上的组件没有数据。就好像那些子组件的渲染在父组件的 getDerivedStateFromProps 之前被调用。
    【解决方案2】:

    感谢@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;
    }
    

    【讨论】:

      猜你喜欢
      • 2021-04-04
      • 2019-12-31
      • 2021-01-06
      • 1970-01-01
      • 2020-11-14
      • 2019-10-05
      • 2021-07-20
      • 2020-09-13
      • 2019-02-10
      相关资源
      最近更新 更多