I am trying to do initialization in ReactJS in a Cordova application. I am somewhat newish to React (this is my first big React project), though not development in general.
I need to do certain events on initialization (Push Notification configuration, analytics, background process setup).
The problem is that for some of these things, I am going to need access to my state store, and specifically my state after login, if the user is logged in (for example, fetching new messages as a background process, which requires a bearer token from my identity provider).
What is the most "React" way to do this? A higher order component to my routing, but below my OIDC provider (keycloak) and store providers? Putting the logic in my login component or "front page" component (both of these seem messy and like anti-patterns to me).
I am guessing the HOC, like so:
<Provider store={store} context={ReactReduxContext}>
<PersistGate loading={<Loading />} persistor={persistor}>
<ConnectedRouter history={history} context={ReactReduxContext}>
<Initialization>
<Layout>
<Route
...
This is a React app with Redux and persistent storage.
Any illumination here would be useful.
Related
I have to find a solution to share information between components in React js.
The use case is that in an online store when a guest tries to add a product to his wishlist he should be redirected to the registration page and after registering it should be automatically added to his wishlist.
I tried with window.localStorage and made it work but I was told that it was not necessary to do it this way, the page is a bit complicated and the components do not have common ancestors the component tree is like this.
<App>
<Routes>
<SearchPage>
<Gallery>
<GalleryItem>
<AddToListButton>
</AddToListButton>
</GalleryItem>
</Gallery>
</SearchPage>
</Routes>
</App>
<App>
<Routes>
<Signin>
</Signin>
</Routes>
</App>
<App>
<Routes>
<Route>
<WishlistPage>
<Wishlist>
</Wishlist>
</WishlistPage>
</Route>
</Routes>
</App>
and I have to pass the button information to the registration page and then make it redirect to its wish list when it registers, apart from useContext what other method could I use?
It depend on the requirements, using localStorage allows you to store user session between tabs, even between sessions.
sessionStorage works similar but it stores data only within single session (for example - one browser tab).
You can try to use React Context API (as you mentioned).
One more is to use centralized store (for example React Redux).
Of course there are some additional browser features like IndexedDb or websql to persist some data for the user, but their support for various browsers can be different.
You have plenty of options, starting with the ones you have out of the box.
Lift the state up The best solution for non complex use cases is to get the state to the parent component and pass down the state value and a function that modifies the state to this sibling components that you want talking to each other.
Context If you have a piece of state that lots of children components are depending on you can create a context, wrap the parent component in a context provider and consume that in the childrens with useContext.
Or you can find libraries for state management here
If this "add to wishlist" action is something that happens in the server I highly recommend react-query. If not, try zustand it's easier to use than redux and feels very similar to context but with less boilerplate and without the need to wrap things in a context provider
I have a React Application and I wish to deploy this behind a load balancer, where the load balancer periodically pings the app to see whether it's healthy. My requirement is to provide a /health endpoint, that can be used for health checking.
What would be the ideal way to implement a health endpoint?
This is something that is required for anyone planning to deploy a React App in a auto-healing fashion
The main page of this App is /dashboard, which is a heavy page. Hence, it cannot be used as a health endpoint.
i.e: I have seen react apps which have /hello kind of endpoints which return a simple message like I am healthy.
I will be answering my own question. After some considerable amount of research and asking around from experienced React developers, the following is the used approach for Including a health endpoint in React Applications.
This requirement came up when containerising the React App to be used in a Kubernetes Environment.
Do NOT ever try to use an existing page as your health check endpoint. Because, your regular pages are heavy and healthcheck endpoints need to be simple.
Hence, create a new route with /health (or a preferable path) and return a simple HTML element. given below is a Simple Route component.
<Route path="/health">
<h3>Hey There!!! The App is Healthy</h3>
</Route>
This being used in a Routes.js file, is given below.
import React from 'react';
import { Switch, Redirect, Route } from 'react-router-dom';
const Routes = () => {
return (
<Switch>
{/* This endpoint will just return you to a dummy HTML with a simple heading tag */}
<Route path="/health">
<h3>Hey There!!! The App is Healthy</h3>
</Route>
{/* All other routes will be defined here */}
{/* Finally you will be redirected to a not found page */}
<Redirect to="/not-found" />
</Switch>
);
};
export default Routes;
The answer above will work but the health endpoint will contain all of the index.html content which is technically unnecessary for the health endpoint.
A much better approach is just adding a file called health in the public folder. Then, when /health is called, the service will return the content of the file, which is faster and much smaller.
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.
A lot of us will be familiar with the enterprise web applications that are the be all and end all of the business data. They are usually a collection of various modules behind a login authentication and role based authorization. Instead of the user login in to various smaller application they login once and have a dashboard/menu of what they have access to.
The user login
Their roles are retrieved and stored in session
Application load with a large menu populated according to their roles (CRM, CMS, no admin panel, etc.)
We have been thinking of how we could leverage some of the newer frameworks out there (Angular, React, Vue) or if we should at all for these kind of applications.
I am a struggling when it come to state management. I understand the idea of managing the state using something like Redux with React for smaller components but if various part of a larger application are completely unrelated to each other I am left wondering how complex and how large this state might get to be?
Using React as an example my root component after login might be (I am not sure as I am not extremely familiar with React yet).
const Root = () => {
return (
<div className="container">
<Router history={browserHistory}>
<Route path="/" component={dashboard}/>
<Route path="/crm" component={crm}/>
<Route path="/cms" component={cms}/>
<Route path="/module1" component={module1}/>
...
<Route path="/moduleN" component={moduleN}/>
</Router>
</div>
)
}
ReactDOM.render(<Root />, document.getElementById('root'));
Is this the better approach even if the multiple routes have nothing in common (the cms doesn't care about the crm) that they should all share the state or would actually reloading the page and going to different smaller more focused single page applications be preferred?
For example, using traditional server side logic to present the menu going to different html file for each modules.
What you are referring to is called lazy loading, that will break down your routes in different JS files and only load them on requests. You can refer to this link on how to use lazy loading in vue.js
https://router.vuejs.org/en/advanced/lazy-loading.html
Here is a way in React (does not seem to be native, correct me if I am wrong)
Dynamic loading of react components
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.