hemoglobin
hemoglobin

Reputation: 841

shouldComponentUpdate for React Tabs

I'm trying to stop re-rendering of tabs. I'll try to explain as best as I can, but please let me know if you need more info or more code.

Currently, I have an app set up inside the tabs which serve as steps that the user has to make to come to the final result. In the first tab, I have states that the user has to set up to apply discounts. It uses

componentDidMount = () => {
        this.updateProductsBasedOnState();
    };

Same as tab two. The issue I have is when you're on tab one and you apply whatever discounts/changes you want and you go to tab two, the tab one will reset once you come back to it. It rerenders.

I've tried using React's Pure Component and also setting up just the shouldComponentUpdate.

If I add the following shouldComponentUpdate on the Parent, it doesn't let tabs be changed at all. If I set it on any of the children, changing the state does not work (as in, you can't add any discounts):

shouldComponentUpdate(nextProps, nextState) {
        return this.state.value != nextState.value;
    }

EDIT: Here's the sandbox link of my tabs!

What else can I try? Can someone point me in the right direction? Thanks!

Upvotes: 2

Views: 268

Answers (1)

Dennis Vash
Dennis Vash

Reputation: 53874

There is a lot to talk about your example, I'll try making it brief and show a brutal example.

The purpose is to mount some Content once and preserve its state on tabs change.

  1. There is no point to use shouldComponentUpdate in App (parent component) because you want to target the Content and not the App itself. You should read more about this life-cycle and whats its purpose.

  2. You are un-mounting the content on every tab switch, try adding the next code in every content component:

const log = id => console.log(`Tab${id} Mounted`);

class AddProducts extends React.PureComponent {
  componentDidMount = () => {
    log(1);
  };
  ...
}

You will notice that every time you switch tabs, your components go over the componentDidMount cycle, that's why they lose their state.

  1. To fix it, you need to render all the components you need in your App and by using its state, define which component to show. There are plenty of ways to do so, the brutal force one is using CSS property display.

Now notice how all components mount once and on tab switch, they preserve their state.

  1. There are many minor tweaks that you should do in your code like avoiding constructor and using babel's class methods and so on.
class App extends React.Component {
  state = {
    activeTabIndex: 0
  };

  handleTabClick = index => {
    console.log('index clicked:', index);
    this.setState({
      activeTabIndex: index
    });
  };

  render() {
    const { activeTabIndex } = this.state;

    return (
      <div className="container quote align-self-center">
        <TabsHeader
          handleTabClick={this.handleTabClick}
          data={initialData.map(data => data.label)}
          activeTabIndex={activeTabIndex}
        />
        <AddProducts
          style={{ display: activeTabIndex === 0 ? 'block' : 'none' }}
        />
        <ApplyIncentives
          style={{ display: activeTabIndex === 1 ? 'block' : 'none' }}
        />
        <QuoteSummary
          style={{ display: activeTabIndex === 2 ? 'block' : 'none' }}
        />
      </div>
    );
  }
}

Edit Q-57960356-TabRender

Upvotes: 3

Related Questions