Skip to content Skip to sidebar Skip to footer

React State Variables Mysteriously Changing Before 'beforeunload' Function

UPDATE: I created a minimum reproducible sample here: https://react-wsaei2.stackblitz.io Editor link: https://stackblitz.com/edit/react-wsaei2 In my app I'm using a sendBeacon func

Solution 1:

You need to define success and loggedOut (and other used variables) as effect dependencies.

useEffect(() => {

  constunlockStory = (e) => {
    e.preventDefault();
    console.log("Inside unlockStory. success, loggedOut:", success, loggedOut);
    if (!success && !loggedOut) {
      console.log("Inside if")
      navigator.sendBeacon(`/api/stories/`, JSON.stringify({body: {locked: true}}));
    }
    e.returnValue = "What's going on?";
  }

  // Add event listener to run code before window closeswindow.addEventListener("beforeunload", unlockStory);
  return() => {
    window.removeEventListener("beforeunload", unlockStory);
  }

}, [success, loggedOut]); // Run on every success or loggedOut change

There is no need to manually remove event listeners as:

React also cleans up effects from the previous render before running the effects next time.

Sometimes is easier to use class based components:

classStartClassextendsReact.Component {
  constructor(props) {
    super(props);
    this.state = {
      loggedOut: false,
      success: false,
      storyObj: {
        segCount: 2
      }
    }
  }

  componentDidMount() {
    this.setState( { loggedOut: true } );
    window.addEventListener("beforeunload", this.unlockStory);
    return() => {
      window.removeEventListener("beforeunload", this.unlockStory);
    }
  }

  handleRefresh = () => {
    let {success, loggedOut} = this.stateconsole.log("Handling refresh: success, loggedOut", success, loggedOut);
    window.location.reload(true);
  }

  unlockStory = (e) => {
    e.preventDefault();
    let {success, loggedOut} = this.stateconsole.log("Inside unlockStory. success, loggedOut:", success, loggedOut);
    if (!success && !loggedOut) {
      console.log("Inside if")
      navigator.sendBeacon(`/api/stories/`, JSON.stringify({body: {locked: true}}));
    }
    e.returnValue = "What's going on?";
  }

  render() {
    return (
      <Containerfluid><Row><Col><p>
            To reproduce:<br/> Open console, then click the Refresh page button below. When the alert pops up check the console and you'll see that the loggedOut variable has changed from true to false.
          </p><p>
            The same behavior occurs when you refresh via the browser, but you can't see the log as the console is cleared upon refresh.
          </p>
          {this.state.loggedOut && <ButtononClick={this.handleRefresh}>Refresh page</Button>}
          </Col></Row></Container>
    );

  }
}

Post a Comment for "React State Variables Mysteriously Changing Before 'beforeunload' Function"