admin管理员组

文章数量:1401673

I would like to make sure that a function is called exactly one time, depending on some props and state.

class MyComponent extends Component {
  state = {
    externalInfoPresent: false,
    infoSaved: false,
  }

  async ponentDidMount() {
    await this.props.refreshExternalInfo();
    this.setState({ externalInfoPresent: true });
    if (this.props.externalInfo !== undefined && !this.state.infoSaved) {
      await this.saveMyInfo();
    }
  }

  async ponentDidUpdate(prevProps) {
    if (prevProps.externalInfo === this.props.externalInfo || this.state.infoSaved) return;
    await this.saveMyInfo();
  }

  async saveMyInfo() {
    if (this.props.externalInfo === undefined || this.state.infoSaved) return;
    // logic for saving stuff to external service
    this.setState({ infoSaved });
  }

  // render and other stuff
}

saveMyInfo() depends on externalInfo being present.

I would like saveMyInfo() to only be called once but it's being called twice with my current logic.

I would like to make sure that a function is called exactly one time, depending on some props and state.

class MyComponent extends Component {
  state = {
    externalInfoPresent: false,
    infoSaved: false,
  }

  async ponentDidMount() {
    await this.props.refreshExternalInfo();
    this.setState({ externalInfoPresent: true });
    if (this.props.externalInfo !== undefined && !this.state.infoSaved) {
      await this.saveMyInfo();
    }
  }

  async ponentDidUpdate(prevProps) {
    if (prevProps.externalInfo === this.props.externalInfo || this.state.infoSaved) return;
    await this.saveMyInfo();
  }

  async saveMyInfo() {
    if (this.props.externalInfo === undefined || this.state.infoSaved) return;
    // logic for saving stuff to external service
    this.setState({ infoSaved });
  }

  // render and other stuff
}

saveMyInfo() depends on externalInfo being present.

I would like saveMyInfo() to only be called once but it's being called twice with my current logic.

Share Improve this question edited Jun 14, 2019 at 16:19 scuttle-jesuit asked Jun 14, 2019 at 15:44 scuttle-jesuitscuttle-jesuit 6781 gold badge6 silver badges16 bronze badges 4
  • There's always a chance the ponent updates while ponentDidMount is still waiting for refreshExternalInfo or refreshExternalInfo causes the props to update and therefore cause ponentDidUpdate to be called. I'm not too clear as to what is exactly happening with this code because it's inplete but it is worth considering this – apokryfos Commented Jun 14, 2019 at 15:49
  • @apokryfos - yes, that is what is currently happening and I don't have a good solution for this:) I just added that saveMyInfo() depends on externalInfo being present which I omitted originally. – scuttle-jesuit Commented Jun 14, 2019 at 15:55
  • Does refreshExternalInfo change the props? If it does then maybe only keep the save in ponentDidUpdate – apokryfos Commented Jun 14, 2019 at 16:27
  • Yes, refreshExternalInfo can change the props. Not always though, only if this.props.externalInfo === undefined and if I only keep it in ponentDidUpdate I can run into a situation when saveMyInfo() doesn't get call at all. – scuttle-jesuit Commented Jun 14, 2019 at 16:54
Add a ment  | 

3 Answers 3

Reset to default 6

If you want it to be called only once, then ponentDidMount is the place (it gets called exactly once in the lifecycle). Therefore you don't need it in ComponentDidUpdate (which gets called everytime a prop changes (after the initial render)!

Lifecycle: https://hackernoon./reactjs-ponent-lifecycle-methods-a-deep-dive-38275d9d13c0

Updated..

I think you Just need to set infosaved to true (this.setstate({infosaved:true}) after you call savemyinfo in ponentdidupdate.

Add an additional flag:

class MyComponent extends Component {
  state = {
    externalInfoPresent: false,
    infoSaved: false,
    saveMyInfoCalled: false,
  }

  async ponentDidMount() {
    await this.props.refreshExternalInfo();
    this.setState({ externalInfoPresent: true });
    if (this.props.externalInfo !== undefined && !this.state.infoSaved) {
      await this.saveMyInfo();
    }
  }

  async ponentDidUpdate(prevProps) {
    if (this.props.externalInfo !== undefined && !this.state.saveMyInfoCalled && !this.state.infoSaved) {
      await this.saveMyInfo();
    }
  }

  async saveMyInfo() {
    this.setState({saveMyInfoCalled: true});
    if (this.props.externalInfo === undefined || this.state.infoSaved) return;
    // logic for saving stuff to external service
  }

  // render and other stuff
}

You probably should call this.setState({saveMyInfoCalled: false}); somewhere if external service fails. So saveMyInfo doesn't get called several times simultaneously but has a second chance if something goes wrong.

class MyComponent extends Component {
  async ponentDidMount() {
    await this.props.refreshExternalInfo();
    await this.saveMyInfo();
  }

  async ponentDidUpdate() {
    await this.saveMyInfo();
  }

  async saveMyInfo() {
    // if we don't have the info then skip for now
    if (this.props.externalInfo === undefined || this.infoSaved) return;

    // keep track that we already saved
    this.infoSaved = true;

    // perform save
  }
}

本文标签: