React Router + back button is resetting my app state - reactjs

I'm using React Router Dom and the BrowserRouter object to enable browser based navigation for a site I'm building. Navigation works well, but if a user hits the back button, the entirety of my App's state is wiped clean.
I'm not sure why this is happening. I've tried searching around, but all of the answers I've found don't mention why App state is getting reset.
Here's my implementation:
<BrowserRouter>
<Switch>
<Route path="/" exact render={()=><LandingPage/>}
<Route path="/about" render={()=><About/>}
</Switch>
</BrowserRouter>
Am I doing something glaringly wrong? Could anyone with experience working with React Router give me some advice? Thanks so much!

If someone like me has this problem in the future and comes here from Google, here's what's going on:
React Router doesn't store state between page loads. It just routes traffic between components and handles history, among other things.
You need a separate state management store to preserve state changes. (Redux was recommended).
Thanks #charlietfl for the info.

Related

Navigate to sibling Routes's Route without page reload in React router 6

Let me present my problem,
I have two subdomains in the same react SPA codebase, say abc.domain.com and xyz.domain.com
I've logically separated the Route block inside Routes for both subdomains.
This is my code at the root level
<BrowserRouter>
<div>
{isabcSubdomain() && <AbcSubDomainApp />}
{isxyzSubdomain() && <XyzSubDomainApp />}
</div>
</BrowserRouter>
Inside AbcSubDomainApp
<Routes>
<Route path="a" element={<A/>}/>
<Route path="b" element={<B/>}/>
</Routes>
Similarly, inside XyzSubDomainApp
<Routes>
<Route path="x" element={<X/>}/>
<Route path="y" element={<Y/>}/>
</Routes>
Now, I am at abc.domain.com/a and want to navigate to xyz.domain.com/x without any page reload, just with a button trigger (say), is there any way to achieve this?
This is not possible, but not only because it is not supported in React.
Each time a browser detects a change to a new domain (subdomains too), a request to a DNS server is triggered (it may be cached but the request is always made), and the browser will then treat the content as coming from a different source.
This happens for very good reasons.
If you were to suddenly switch domains without reloading, how would the browser know which site data to use?
If you switched domains without realizing, you might accidentally enter private information into the wrong website!
I recommend you do not pursue this functionality within your website. Having two copies of the exact same code on different websites is not a good solution.

React app does not render inside Facebook instant game iframe

I have a react app which does not render when zipped and loaded into facebook instant game platform. It generates logs such as below, that clearly show that the actions are firing. See the logs with Middleware ACTION-NAME below.
If someone can give me ideas on what could be going wrong, that would be great. Does JSX in an iframe need some special permissions to write to the #root tag?
I solved it thus,
I am using BrowserRouter in react for navigation. I had to change the route path I wanted to load initially from / to * .
- <Route exact path="/">
+ <Route exact path="*">
It seems like initially, when running the game inside the iframe, the route path did not match / .

How to render a page to base url in react

I need to render a page for base url in react. I defined base url as,
<Router basename="/baseUrl">
<Switch>
<Route path={"/childUrl"}
</Switch>
</Router>
I am able to render page via /baseUrl/childUrl. When accessing, /baseUrl it redirects to /baseUrl/childUrl. How can I set a different page to /baseUrl
I know this is old, but in case anyone else stumbles upon this I would recommend using redux-first-router. It lets you dispatch actions either by changing the url in your browser, or the regular react way. This lets you control how components are rendered and keep the state of your application in sync with the url, without having multiple sources of truth.
Michael Sargent did a brilliant explanation, which can be found here.
And of course, you can also check out the git repo.

Remounting all react child components after root state change

I'm building a pretty large application and would like to get some insight on the best way to re-render the application based on a root component state change.
Sample Architecture
<Route path="/" component={App}>
<Route component={Layout}>
<IndexRoute component={Page} />
<Route path={page} component={Page}></Route>
...
</Route>
<Route component={Layout}>
<IndexRoute component={Page} />
<Route path={page} component={Page}></Route>
...
</Route>
In my architecture after a successful login i'm storing the users data in my App component. Every user has a client key which is used as the identifier as to which clients database/data to display. The behavior i would like to accomplish would be to update my current page with the new clients data after the a client change.
Now i could pass my data down to my components as props from my App component but i think this would be inefficient because of two reasons.
I would have to get the data for all my routes before rendering my App component.
My data would become "stale" until i re-render my App component.
Because of these reason i decided to let each page fetch it's own data using the componentWillMount life cycle hook, and passing the data down as props to the pages child components. This works for me because i'm able to fetch fresh data for each page upon navigation.
What i'm currently experiencing is that after a client change my application re-renders but since my current page has already mounted it doesn't fetch the new client data. But everything works as expected if i navigate away from the current page and then back to the page.
One solution i have in mind is to pass the users data down to each page and use the componentWillReceiveProps life cycle hook and perform a comparison check in order to fetch new data. I would like to prevent that if at all possible since my application will have 40+ pages.
Any suggestions would be greatly appreciated.
What you have mentioned about
pass the users data down to each page and use the
componentWillReceiveProps life cycle hook and perform a comparison
check in order to fetch new data.
is perfectly fine. Few examples of such a pattern in the wild:
Redux repository real world example
React Router core team recommends this method too as per issue here.

Pushstate on React

Is it possible to refresh the react component route on history pushState?
For ex :
<Route path="/" component={App}>
<Route path="/search/:query/" component={search}/>
</Route>
this.props.history.pushState(null,"/search/test");
Suppose if i am on the search route itself, and in my code am pushing the state,is it possible to refresh the route?
Apparently not, and it's not something the react-router maintainers are planning to support since that's not how react works (i.e. only if virtual dom changes will react reload the component). See this thread for the context of the discussion.
Angular blows everything away and reinitializes all of it. React will do a virtual DOM diff. None of your willMount, didMount etc. hooks will be called. But you'll get "already mounted" hooks like componentWillReceiveProps and componentDidUpdate.
There could be 2,000 people asking for this feature to try to reload their data, but React (not React Router) just doesn't work that way.

Resources