ELD
ELD

Reputation: 338

How to call setState with componentDidMount without causing extra calls to render?

I have a problem with componentDidMount: everytime that i use setState in componentDidMount it calls render several times in child components, and I don't know why... look:

componentDidMount() {
  const firstName = localStorage.getItem('nameLoggedUser');
  const lastName = localStorage.getItem('lastNameLoggedUser');
  const fullName = `${firstName} ${lastName}`.toLowerCase();

  const loggedUserIs = localStorage.getItem("user-role");
  const emailLoggedUser = localStorage.getItem('emailLoggedUser');

  if (loggedUserIs === 'full') {
    axios.get(`/api/menuDomain`)
      .then(res => this.setState({
        domain: res.data
      }))
      .catch(err => console.log(err))
  }
}

It gives this: enter image description here

But, if I use ComponentDidUpdate, it gives: enter image description here

That is correct, but the AJAX call is not happening...

I want to make the AJAX call and not have it render several times... But I don't know how... Could someone help me? Please???

And I am using react-router too:

    return (
      <Router>
        <Switch>
          <Route path="/login" component={Login} />
          <Route exact path="/" render={() =>
            <Overview
              {...myProps}
            />
            } 
            />

          <Route path="/list" render={() =>
            <Graphic
              {...myProps}
            />
          } />
        </Switch>
      </Router>
    );
  }
}

Upvotes: 1

Views: 90

Answers (1)

Matt Carlotta
Matt Carlotta

Reputation: 19762

First, never wrap your routes within a stateful component. Instead, the routes should be a stateless function that just returns the same JSX route elements. For the example above, you should use a HOC that wraps your protected routes and is only concerned with authentication: https://stackoverflow.com/a/53197429/7376526

Second, you shouldn't be storing the logged in user in plain text within local storage. Instead, it and possibly the password should be stored within a JWT token (or within some sort of hashed plus salted token) or perhaps within a secured cookie and then decoded and compared against server-side. How you're currently setting it to localStorage is incredibly insecure and anyone can simply set a user's first and last name and their "user-role" and gain access to their account.

Third, each container should handle and fetch relevant data and pass it to a relevant component for display. For performance, you should compartmentalize your retrieved data to relevant data for that particular component. Since you have multiple routes, fetching everything at once is wasteful. For example, fetch Overview data inside of a FetchOverview container's componentDidMount, then pass it down to a DisplayOverview child component for display. Read this for more information on containers and components: https://medium.com/@dan_abramov/smart-and-dumb-components-7ca2f9a7c7d0

Upvotes: 2

Related Questions