Reactjs cookie is empty in subroute using universal-cookie - reactjs

everytime before the app loads i check the cookie in order to determine where to navigate.
I check the cookies in a method inside of App.js.
These are the three Routes iam using in the App.js named checkCookies().
import Cookies from "universal-cookie";
import _ from "lodash";
checkCookies();
class App extends Component {
render() {
return (
<Provider store={store}>
<BrowserRouter>
<Switch>
<Route
exact
path="/car"
component={Car}
/>
</Switch>
<Switch>
<Route
exact
path="/car/bmw"
component={BMW}
/>
</Switch>
<Switch>
<Route exact path="Ferrari" component={Ferrari} />
</Switch>
</BrowserRouter>
</Provider>
)
}
}
The code for the checkCookies method is the following:
checkCookies(){
let model = cookies.get("model");
if(_.isEmpty(model) || model==""){
// do this
}
}
when i try to access a cookie in the route "/car" it works but when i try to access the cookie in the route "/car/bmw" or "/car/ferrari" its not working.
But when i rename it from "/car/bmw" just to "/bmw" it works.
But i dont want to change the url name.
The url should stay how it is.
How can i dot it?

Related

Browser Router (React app ) on Github not working

i have a little React app project and i have deployed it in Github. It works, even i am using import { BrowserRouter, Link, Switch, Route } from "react-router-dom"; to routing and works ... for my home component but not for the rest. This is my code: `class App extends React.Component {
render() {
return <div>
<BrowserRouter basename={process.env.PUBLIC_URL}>
<Switch>
<Route exact path ="/" component={Show} />
<Route exact path="/contact" component={Contact}/>
</Switch>
</BrowserRouter>
</div>
}
}
export default App;`
I have used this in local machine without the "basename" and worked. Now, in the github server my problem is that it is currently showing my first component when you visit my app main url but is not working for the other component, "/contact". I am not sure if i have to use the '<Link to ' property. Anyway, i just want to know why is working for my main url path (https://namegithub.github.io/main-path/) but not for any other path (https://namegithub.github.io/main-path/contact).
Sorry is a dummy question but actually i am just giving my first steps in React.
Thanks!
you can you this code
import {BrowserRouter as Router,Switch,Route} from 'react-router-dom'
return <div>
<Router basename={process.env.PUBLIC_URL}>
<Switch>
<Route exact path ="/" component={Show} />
<Route exact path="/contact" component={Contact}/>
</Switch>
</Router>
</div>

Adding MsalAuthenticationTemplate for some routes causes all routes to require login

I’ve got a ReactJS website in which I am trying to use "#azure/msal-react": "^1.0.0-beta.1", and ran into some issues that have me flummoxed.
Most of my pages are open to the public. Some require login. If I add the MSALAuthenticationTemplate as below (but with interactionType=Redirect), as soon as I start the site, it asks me to login. I thought it would only do that if I hit a route that was in the AuthenticationTemplate.
Using InteractionType Popup causes the SPA to throw an exception on startup
Error: Objects are not valid as a React child (found: object with keys {login, result, error}). If you meant to render a collection of children, use an array instead. in p (at App.tsx:44)
All of my routes are, for some reason, coming back to the home page instead of loading the relevant components, event with the AuthenticationTemplate commented out.
I had this pretty much working using straight Javascript, but was running into ESLint issues when publishing, so I thought Typescript would help me fix those. But now it’s just broke.
render() {
initializeIcons();
return (
<MsalProvider instance={msalClient} >
<div className="d-flex flex-column h-100">
<TopMenu />
<div className="container-fluid flex-grow-1 d-flex">
<div className="row flex-fill flex-column flex-sm-row">
<BrowserRouter>
<MsalAuthenticationTemplate
interactionType={InteractionType.Popup}
errorComponent={this.ErrorComponent}
loadingComponent={this.LoadingComponent}>
<Switch>
<Route path="/addevent">
<AddEvent />
</Route>
<Route path="/mydashboard">
<MyDashboard />
</Route>
</Switch>
</MsalAuthenticationTemplate >
<UnauthenticatedTemplate>
<Switch>
<Route path='/'>
<Home />
</Route>
<Route path="/about">
<About />
</Route>
<Route path="/contactus">
<ContactUs />
</Route>
<Route path="/faq">
<Faq />
</Route>
<Route path="/fetchevents">
<FetchEvents />
</Route>
<Route path="/gettingstarted">
<GettingStarted />
</Route>
<Route path="/partners">
<Partners />
</Route>
<Route path="/privacypolicy">
<PrivacyPolicy />
</Route>
<Route path="/sponsors">
<Sponsors />
</Route>
<Route path="/termsofservice">
<TermsOfService />
</Route>
<Route path="/userstories">
<UserStories />
</Route>
</Switch>
</UnauthenticatedTemplate>
<div>
<Footer />
</div>
</BrowserRouter>
</div>
</div>
</div>
</MsalProvider>
);
Let's start with the UnauthenticatedTemplate. If the user is authenticated, children of the component will not show. So I guess you don't want to use it there. It's typical usage is for Login/Logout button for example.
Another problem is that if you are using MsalAuthenticationTemplate as the parent of the Switch and Route components. The problem is that you are guarding switch and routes from unauthenticated users, but this components should always be available without authentication, if you don't want to protect whole page.
During rendering React will go through your components one by one and first child of the BrowserRouter component it will try to render is MsalAuthenticationTemplate and since user is not authenticated, it will redirect user to login page.
This is quote from react-router docs:
A Route is always technically “rendered” even though it’s rendering null. When the 's path matches the current URL, it renders its children (your component).
Because of this the children of the route will only be rendered if the route will be hit. So you need to put MsalAuthenticationTemplate component as a direct child of the route, or even inside such component:
<Switch>
<Route path="/addevent">
<MsalAuthenticationTemplate
interactionType={InteractionType.Redirect}
authenticationRequest={loginRequest}
>
<AddEvent />
</MsalAuthenticationTemplate>
</Route>
...
</Switch>
As for all the webpages redirected to your home screen, you should add exact keyword to your Home route. This attribute causes it to not match all other routes also. Single '/' matches all your other routes.
In addition to the answer already provided, there is a way (cleaner in my opinion) you can configure MSAL react to take advantage of the router's navigate functions when MSAL redirects between pages in your app.
Here is how it works:
In your index.js file you can have something like so:
import { PublicClientApplication, EventType } from "#azure/msal-browser";
import { msalConfig } from "./authConfig";
export const msalInstance = new PublicClientApplication(msalConfig);
ReactDOM.render(
<React.StrictMode>
<Router>
<ThemeProvider theme={theme}>
<App pca={msalInstance} />
</ThemeProvider>
</Router>
</React.StrictMode>,
document.getElementById('root')
);
As shown, you need to pass msal instance as props to your main App.
Then in your App.js where you setup your routes, you will need to do the following:
import { MsalProvider } from "#azure/msal-react";
import { CustomNavigationClient } from "NavigationClient";
import { useHistory } from "react-router-dom";
function App({ pca }) {
// The 3 lines of code below allow you to configure MSAL to take advantage of the router's navigate functions when MSAL redirects between pages in your app
const history = useHistory();
const navigationClient = new CustomNavigationClient(history);
pca.setNavigationClient(navigationClient);
return (
<MsalProvider instance={pca}>
<Grid container justify="center">
<Pages />
</Grid>
</MsalProvider>
);
}
function Pages() {
return (
<Switch>
<Route path="/addevent">
<AddEvent />
</Route>
<Route path="/mydashboard">
<MyDashboard />
</Route>
<Route path='/'>
<Home />
</Route>
<Route path="/about">
<About />
</Route>
<Route path="/contactus">
<ContactUs />
</Route>
<Route path="/faq">
<Faq />
</Route>
// your other routes
</Switch>
)
}
And here is the helper function used in App.js that enables navigation by overriding the the default function used by MSAL
import { NavigationClient } from "#azure/msal-browser";
/**
* This is an example for overriding the default function MSAL uses to navigate to other urls in your webpage
*/
export class CustomNavigationClient extends NavigationClient{
constructor(history) {
super();
this.history = history;
}
/**
* Navigates to other pages within the same web application
* You can use the useHistory hook provided by react-router-dom to take advantage of client-side routing
* #param url
* #param options
*/
async navigateInternal(url, options) {
const relativePath = url.replace(window.location.origin, '');
if (options.noHistory) {
this.history.replace(relativePath);
} else {
this.history.push(relativePath);
}
return false;
}
}
You can then use AuthenticatedTemplate on your private pages and UnauthenticatedTemplate on the public pages. For example if you have have addEvent.js (private) and Home.js (public), you will have each components like so:
export function Home() {
return (
<>
<AuthenticatedTemplate>
<p>Welcome Home - it's public</p>
</AuthenticatedTemplate>
</>
);
}
export function AddEvent() {
return (
<>
<UnauthenticatedTemplate>
<Typography variant="h6">
Add event - it is a private page
</Typography>
</UnauthenticatedTemplate>
</>
);
}
Here is a complete example on how to use react-router with msal react for your reference.

How to defend routes in reactJS

I came across a problem which I dont know how to fix. I dont even know where to start.
The problem is next : I have url "localhost:4000/" If I will type url "localhost:4000/homepage" It will redirect me to my home page,But i want to restrict this access if token is not preserved.
Here are my routes :
import React from "react";
import { BrowserRouter as Router, Switch, Route } from "react-router-dom";
import LogIn from "./components/LogIn/Login";
import Register from "./components/Register/Register";
import Homepage from './components/HomePage/HomePage'
import Profile from './components/Profile/Profile'
import Posts from './components/addPostUI/Posts'
import "./app.css";
function App() {
return (
<Router>
<div className="App">
<Switch>
<Route path={"/"} exact component={LogIn} />
<Route path={"/login"} component={LogIn} />
<Route path={"/registration"} component={Register} />
<Route path={'/homepage'} component={Homepage} />
<Route path={'/profile'} component={Profile} />
<Route path={"/posts"} component={Posts} />
</Switch>
</div>
</Router>
);
}
export default App;
Any suggestions on how to restrict access and defend my routes?
There are many ways to restrict your Routes conditionally. The basic approach you can follow here is:
<Router>
<Switch>
<Route
path='/homepage'
render = {() => {
if(accessToken || localStorage.getItem('accessToken')) {
return <Homepage />;
} else {
return <Redirect to='/login' />;
}
}}
/>
</Switch>
</Router>
You can follow along with these steps whenever there is a need for conditional routing.
First determine what you want to authenticate users by, then you can do the following inside the page you want to protect, before the page renders.
if (failed access condition) return <Redirect to='/some route you want to redirect to' />
Be sure to import Redirect like this:
import { Redirect } from 'react-router-dom'
Also Consider
If you have a database, be sure to restrict access to the data based on the access token as well and don't depend on client side code to protect data.

Get router value from url in react

I have a react app, and a component that is supposed to load a set of value of the url
<PersistGate persistor={rootStore.persistor}>
<Router history={history}>
<ErrorBoundary>
<Preloader history={history} /> <== this need to read the url
<PasswordChecker></PasswordChecker>
<RouteDispatcher></RouteDispatcher> <== this contain the list of routes
</ErrorBoundary>
</Router>
</PersistGate>
In my RouteDispatcher path I have setup the route like this :
<BrowserRouter>
<Switch>
<PrivateRoute path="/ws/:ws/pj/:pj/ds/:ds" component={HomeDatastore} />
<PrivateRoute path="/ws/:ws/pj/:pj" component={HomeProject} />
<PrivateRoute path="/ws/:ws" component={HomeWorkspace} />
</Switch>
</BrowserRouter>
how would I get the value of ws=:ws pj=:pj etc...
I was thinking of doing it with a regex, but I wonder if there is a better way. Preloader is outside the routeDispatcher, so I don't seem to find a good way to get the value.
React router provides params into the component. Check props.match.params. I see that you have a custom component PrivateRoute so first check props in PrivateRoute.
May be try using useParams() hook. It gives you a way to access the URL params
Reference: https://blog.logrocket.com/react-router-hooks-will-make-your-component-cleaner/
Sandbox: https://codesandbox.io/s/react-router-useparams-hooks-q8g37
This might help you get started with it
import { useParams } from "react-router-dom";
function ComponentName() {
let params = useParams();
return (
<div>
{params.ws}
{params.pj}
</div>
);
}

Can i use a laravel router and a react router together?

Example ....
i Have route React
function App() {
return (
<React.Fragment>
<Router>
<Switch>
<Route exact path="/" component={list} />
<Route exact path="/p/:id" component={Post} />
</Switch>
</Router>
</React.Fragment>
)
}
export default App;
And I Have Route in Laravel
Screenshot : http://prntscr.com/ov80dm
but when i am try .. i get blank page ...
anyone know the solution ?
No, you can't but you can write a wildcard any route in web.php, so that every route get redirected to a single view where the js is imported. Then let the react router work accordingly.
Route::get('/{any}', function () {
return view('base.blade')
})->where('any', '.*');

Resources