user3297198 user3297198 - 2 months ago 14
React JSX Question

React content change based on selected menu with caching

I have this code.



class Component {

state = {
selectedView: 'foo',
}

onMenuClicked(event, menuItem) {
switch(menuItem) {
case 'foo':
this.setState({ selectedView: 'foo'})
break;
case 'bar':
this.setState({ selectedView: 'bar'})
break;
}
}

renderBar() {
return <Bar />
}

renderFoo() {
return <Foo />
}

renderContent() {
switch(this.state.selectedView) {
case 'foo':
return this.renderFoo();
case 'bar':
return this.renderBar();
}
}

render() {
return(
<div>
<Menu onMenuSelected((e, menuItem) => this.onMenuClicked(e, menyItem)) /> // items foo and bar
{this.renderContent()}
</div>
)
}





This works fine. However, since foo and bar component are very heavy and the chances of user toggling between these components are high, I would like to have this kind of flow,


  • On page load, render foo

  • If bar is clicked for the first time, render bar

  • For all subsequent menu changes, just hide/show the foo/bar components (based on menu clicked) and don't reload them on every menu change.



I need to adapt my code (the cleanest way possible) to have such behavior. Any help would be appreciated. Thank you.

Answer

One way to handle this would be to use display: none on your elements and keeping track of which elements have already been displayed. This way redux will always keep the rendered component in the DOM and only update the display value.

class Component {

  state = {
    selectedView: 'foo',
    foo: true // to indicate that foo has been rendered
  }

  onMenuClicked(event, menuItem) {
    switch(menuItem) {
      case 'foo':
        this.setState({ selectedView: 'foo', foo: true})
        break;
      case 'bar':
        this.setState({ selectedView: 'bar', bar: true})
        break;
    }
  }

  renderBar() {
    const selected = this.state.selectedView === 'bar';

    if (!this.state.bar) {
        return <div/> // don't render bar at all
    }
    return <div style={{display: selected ? 'block' : 'none'}}>
        <Bar />
    </div>
  }

  renderFoo() {
    const selected = this.state.selectedView === 'foo';

    if (!this.state.foo) {
        return <div/> // don't render foo at all
    }
    return <div style={{display: selected ? 'block' : 'none'}}>
        <Foo/>
    </div>
  }

  renderContent() {
    return <div>
        {this.renderFoo()}
        {this.renderBar()}
    <div/>
  }

  render() {
    return(
      <div>
        <Menu onMenuSelected((e, menuItem) => this.onMenuClicked(e, menyItem)) /> // items foo and bar
        {this.renderContent()}
      </div>
    )
  }