Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

React history.push reloads component. Want it to load only once

When redirecting after component loads using history.push - my component is rendered again. Causing componentDidMount() function to run twice.

Here's a simplified snippet of one of my components. I want the componentDidMount() to run only once - and it works as expected without the history.push. But when i add the history.push - it loads twice. (Same happens if i use Redirect from react-router)

import * as React from "react";
import { history } from "../../configureServices";
import { explore } from "../../routes";

export class WelcomeComponent extends React.Component<object, object> {
  componentDidMount() {
    // tslint:disable-next-line:no-console
    console.log("componentDidMount");
    history.replace(explore);
  }
  render() {
    return <div />;
  }
}

Console:

componentDidMount
componentDidMount

Would love to find a way to have this run only once.

Edit: Thank you for the responses everyone. I'm going to post a quick code snippet and then post a Fiddle in a bit.

--- Update:

I am using React-Router. I build the history (along with some other services) in the configureServices.ts file.

// configureServices.ts
import { createBrowserHistory } from "history";

export const history = createBrowserHistory();

My index.ts looks like this:

import { history } from "./configureServices";

ReactDOM.render( 
  <Provider {...stores}> 
<AppComponent history={history} /> 
  </Provider>, 
document.getElementById("root") );

And my AppComponent which has all the routes looks like this:

import { History } from "history";
import { Route, Switch } from "react-router-dom";
import { Router } from "react-router-dom";
import * as Routes from "../../routes";

...
// Import Components
...

interface Props {
  history: History;
  ...
}

export class AppComponent extends React.Component<Props, {}> {
  componentDidMount() {
    this.props.authStore && this.props.authStore.authenticate();
  }

  render() {
    return (
      <Router history={this.props.history}>
        // For toasts, please ignore for this example
        <ToastProvider
          placement={toastPlacement}
          autoDismissTimeout={toastDismissTimeout}
        >
            // Main App Div = Navbar + Components

          <div className="font-sans flex flex-col h-full text-phi-green-munsell bg-phi-gunmetal-rich-dark">
            <NavBarComponent />

            // This is where the routes are
            <div className="container mx-auto p-2 md:p-3 lg:p-4 justify-start">
              <Switch>
                <Route
                  exact={true}
                  path={Routes.homePage}
                  component={HomepageContainer}
                />
                <Route
                  exact={true}
                  path={Routes.logOut}
                  component={LogOutContainer}
                />
                <Route
                  exact={true}
                  path={Routes.welcome}
                  component={WelcomeContainer}
                />
                <Route
                  path={Routes.explore}
                  component={ExploreComponent}
                />
                <Route
                  path={Routes.searchResults}
                  component={SearchResultsComponent}
                />
              </Switch>
            </div>
            <Footer />
            <DevTools position={mobxDevToolsPosition} />
          </div>
        </ToastProvider>
      </Router>
    );
  }
}

Thank you again for helping me with this.

like image 974
Panda Avatar asked Jan 29 '19 17:01

Panda


People also ask

How do you stop refresh the component in react?

How do you refresh a page without reloading in React? Method 1: Refresh a Page Using JavaScript window. location. reload(false); This method takes an optional parameter which by default is set to false.

Does history push unmount component?

Calling history. push() inside of a component seems to cause the entire react component to unmount and remount; causing pointless remote service calls.

How do I clear push and react history?

push(`/route`); This will clear the history and change for a new one. Save this answer.

Does react redirect refresh page?

Does react-router dom reload the page? react-router-dom allows us to navigate through different pages on our app with/without refreshing the entire component. By default, BrowserRouter in react-router-dom will not refresh the entire page.


2 Answers

There are a couple of things that could cause your component to remount.

  1. If the react component tree above this component changes. This might be caused by something like having multiple Route components which display this component, but the path changes from one to the other. Even though the same component is ultimately displayed, the Route component which was matched changed.
  2. If the key for this component changed. If you are doing something like using randomly generated keys, or using array indices for keys and reordering elements, then you will see components remount.
like image 176
Matt H Avatar answered Nov 12 '22 18:11

Matt H


I wanted to update the question since I figured it out. I was calling history.replace(explore) in componentDidMount() - which (for reasons I don't understand well) - was causing the react component tree above this component to change as Matt H mentioned. I ended up using Redirect from react-router-dom and returning the redirect in render. Like:

render() {
    return <Redirect to={explore} />;
  }

So, I instead of making all calls in componentDidMount() and redirecting in that function as well. I made the api calls in componentDidMount() and used render to redirect. Happy it worked and thank you all for responding to my question.

like image 3
Panda Avatar answered Nov 12 '22 19:11

Panda