title: How does react trigger componentDidMount with safari cache?
body: <p><strong>React 16 triggers <code>componentDidMount()</code> when going back in Safari, even tho the component never unmounted. How does react know when to mount?</strong></p>
  
  <pre><code>class Foo extends React.Component {
    state = {
      loading: false
    }
  
    componentDidMount() {
      // when going back in safari
      // triggers in react 16, but not in 15.3 or preact
      console.log('mounted');
    }
  
    componentWillUnmount() {
      // will never trigger
      console.log('will unmount');
    }
  
    leave() {
      this.setState({
        loading: true
      });
      setTimeout(() =&gt; {
        window.location.href = 'https://github.com/';
      }, 2000);
    }
  
    render() {
      return this.state.loading ? &lt;div&gt;loading...&lt;/div&gt; : &lt;button onClick={this.leave.bind(this)}&gt;leave&lt;/button&gt;;
    }
  }
  </code></pre>
  
  <h2>Background</h2>
  
  <p>Safari uses bfcache. If you go back it takes the last page from cache.</p>
  
  <p>When using react 15.3 or libraries such as preact, leaving the page will not trigger <code>componentWillUnmount</code> and going back will not trigger <code>componentDidMount</code>.</p>
  
  <p>This behaviour causes several issues - for example when you set your page state to <code>loading</code> before redirecting. If the user goes back, the state is still set to loading and you cannot even reset the state using <code>componentDidMount</code>, because it never triggers.</p>
  
  <p>There is a <a href="https://stackoverflow.com/questions/8788802/prevent-safari-loading-from-cache-when-back-button-is-clicked">solution</a>, by using <code>onpageshow</code>, but since it <a href="https://bugs.webkit.org/show_bug.cgi?id=156356" rel="noreferrer">only triggers one time</a>, you have to reload the whole page using <code>window.location.reload()</code>. <strong>This is also the reason react cannot rely on this solution.</strong></p>