Search code examples
reactjsturbolinks

inconsistent state and display in React when using browser 'back' button


I am using React 16.1.1 (with the react-rails gem) in a Rails 5.1 app.

The React components on a specific page work fine, except when going back to this page with the browser 'back' button (tested with firefox / chrome / safari). In that case, the display is inconsistent with the state of the component. I've setup a demo of the problem: https://lit-bastion-28654.herokuapp.com/.

Steps to reproduce:

  1. be on /page1
  2. click the 'selection mode' button, it sets 'selectionMode' to true
  3. click 'page 2'
  4. use 'back' button to go back to page 1
  5. EXPECTED BEHAVIOUR: the button is grey (selectionMode is reset to false when component loaded). OBSERVED BEHAVIOUR: the button is still blue?!

There, you can see that the button is blue, as if selectionMode was true, but the react browser plugin shows that selectionMode is false. The React browser plugin shows false information: it shows that the button does not have the 'btn-primary' class (which is normal if selectionMode is false), but you can obviously see that in the DOM, it has the 'btn-primary' class, since it is appears blue.

This is my code:

page1.html.erb:

<%= react_component("EditableCardList", { editable: true }) %>

editable_card_list.js.jsx:

class EditableCardList extends React.Component {
  constructor(props) {
    super(props);
    this.state = {
      selectionMode: false
    };

    this.toggleSelectionMode = this.toggleSelectionMode.bind(this);
  }


  toggleSelectionMode() {
    this.setState(prevState => ({ selectionMode: !prevState.selectionMode }));
  }


  render() {
    if (this.props.editable === true)
      return (
        <div>
          <div className="row card-buttons">
            <div className="col-md-12">
              <div className="pull-left">
                <ManageCardsButtons
                  selectionMode={this.state.selectionMode}
                  toggleSelectionMode={this.toggleSelectionMode}
                />
              </div>
            </div>
          </div>
        </div>
      )
  }
}

manage_cards_buttons.js.jsx:

class ManageCardsButtons extends React.Component {
  constructor(props) {
    super(props);
  }


  render() {
    return (
      <span>
        <button type="button" className={`btn btn-default btn-sm ${this.props.selectionMode ? 'btn-primary' : ''}`}  onClick={this.props.toggleSelectionMode}>Selection mode</button>

        { this.props.selectionMode && <span>selection mode</span> }
      </span>
    )
  }
}

So my question is: How to make sure that, after using 'back' in the browser, the button is rerendered properly (and appears grey instead of blue)?

The issue may be related with turbolinks and caching, but I've not been able to figure it out yet.


Solution

  • React and TurboLinks conflict, so my final solution was to disable TurboLinks caching on that specific page.