Avoid loading data passed as props with React Router

Viewed 156

I want to pass some data to the MainScreen component, but in the following example, loadData() is being called even when I access the /about route.

I could pass the loadData function and call it from MainScreen, but I don't want the component to have this responsibility.

How can I load the data only when the route is accessed?

class App extends React.Component {
  loadData = () => {
    console.log("Loading data");
    return {
      something: 123
    };
  }
  render() {
    return (
      <Router>
        <Switch>
          <Route exact path="/">
            <MainScreen data={this.loadData()} />
          </Route>

          <Router path="/about">
            <About />
          </Router>
        </Switch>
      </Router>
    );
  };
}
1 Answers

This behavior is not due to use react router, but because of React architecture.

This line

<Route exact path="/">
    <MainScreen data={this.loadData()} />
</Route>

will look like something like this after transpiling

React.createElement(Route, { exact: true, path: "/" }, 
    React.createElement(MainScreen, {data: this.loadData()}, null))

So code written with JSX will be transpiled to plain JS and then run. And as you may see from code above, MainScreen element will be created despite of whether it will be rendered by Route or not (React.createElement(MainScreen, {data: this.loadData()}, null) will be called as it is argument to another React.createElement which is used to create Route component)

Exactly your problem can be solved using render props. This way, you'll pass render function to Route component, and it will be called only in case of route match.

class App extends React.Component {
  loadData = () => {
    console.log("Loading data");
    return {
      something: 123
    };
  }
  render() {
    return (
      <Router>
        <Switch>
          <Route exact path="/" render={() => 
            <MainScreen data={this.loadData()} />}
          </Route>

          <Router path="/about">
            <About />
          </Router>
        </Switch>
      </Router>
    );
  };
}

Here is the sample

Related