React redirect not loading the page at first try. Need to do a hard refresh on browser to display the page - redirect

I am a newbie to react have implemented a redirect logic depending on what response I am getting back from an API. Now based on the API response I am seeing that the URL is changing on the browser but nothing is getting displayed. When I refresh the link in the browser tab then the page is getting loaded.Looked at similar issues in stackoverflow but nothing seems to work in my situation. Any help/ guidance in this regard will be helpful. Thanks in advance
import ReactDOM from 'react-dom';
import {
Route,
Switch,
HashRouter,
withRouter,
Redirect
} from 'react-router-dom';
<HashRouter>
<Switch>
<Route exact path="/" component={withRouter (RoutePage)}>
{UserStatus === 'Migrated' && audience === 'admin'
? <Redirect to="/adminConfirmation" />
: null
}
{UserStatus === 'Repeated' && audience === 'admin'
? <Redirect to="/admin-hub" />
: null
}
{UserStatus === 'Migrated' && audience === 'user'
? <Redirect to="/userConfirmation" />
: null
}
{UserStatus === 'Repeated' && audience === 'user'
? <Redirect to="/user-hub" />
: null
}
</Route>
<Route exact path="/admin-hub" component={withRouter (Admin)} />
<Route exact path="/user-hub" component={withRouter (UserHub)} />
<Route
exact
path="/adminConfirmation"
component={withRouter(AdminConfirmation)}
/>
<Route
exact
path="/userConfirmation"
component={withRouter(UserConfirmation)}
/>
</Switch>
</HashRouter>

Related

Navigatiion Component using #mui/material not rendering [duplicate]

I have been learning React for few days and I wrote simple project (single page application). Problem is that my page doesn't show anything - it's a blank page.
App.js
import './App.css';
import {BrowserRouter as Router,Routes,Route,} from "react-router-dom";
import { Home } from './components/Home';
import { Wallet } from './components/Wallet';
function App() {
return (
<Router>
<Routes>
<Route exact path="/" component={Home}/>
<Route path="/wallet" component={Wallet}/>
</Routes>
</Router>
);
}
export default App;
Wallet.js
import React from "react";
export function Wallet() {
return (
<div>
<h1>Wallet Page!</h1>
</div>
);
}
Home.js
import React from "react";
export function Home() {
return (
<div>
<h1>Home Page!</h1>
</div>
);
}
So when I go to http://localhost:3001/ or http://localhost:3001/wallet I receive blank page. Could someone point me where I made a mistake?
In react-router-dom#6 the Route components render the routed content on the element prop as a ReactNode, i.e. as JSX. There is no longer any component, or render and children function props.
Routes and Route
declare function Route(
props: RouteProps
): React.ReactElement | null;
interface RouteProps {
caseSensitive?: boolean;
children?: React.ReactNode;
element?: React.ReactNode | null;
index?: boolean;
path?: string;
}
Move the components into the element prop and pass them as normal JSX instead of as a reference to a component.
<Router>
<Routes>
<Route path="/" element={<Home />} />
<Route path="/wallet" element={<Wallet />} />
</Routes>
</Router>

In SolidJS, How Do I Do a Fallback Route?

I'm new to Solid JS, coming mainly from a React background. I'm using Solid and Solid-App-Router right now for the first time.
I'm trying to design routes with a fallback, meaning if an endpoint is put into the URL that does not exist, it will redirect to a default location. My problem is this fallback is executing no matter what, overriding all my other routes.
I'll add that namedLazy works great and is simply a wrapper to support named exports with SolidJS lazy(). Here is my routing code:
import { namedLazy } from '../../utils/solidWrappers';
import { Routes, Route } from 'solid-app-router';
import { isAuthenticated } from '../../resources/AuthResources';
const Welcome = namedLazy(() => import('./Welcome'), 'Welcome');
const Categories = namedLazy(() => import('./Categories'), 'Categories');
const Redirect = namedLazy(() => import('../UI/Redirect'), 'Redirect');
export const AppRoutes = () => {
return (
<Routes>
<Route path="/welcome" element={<Welcome />} />
{isAuthenticated() && (
<Route path="/categories" element={<Categories />} />
)}
<Route path="*" element={<Redirect />} />
</Routes>
);
};
And here is my Redirect component:
import { useNavigate } from 'solid-app-router';
export const Redirect = () => {
const navigate = useNavigate();
navigate('/welcome');
return <></>;
};
This kind of fallback route design works in react-router, however it's not working for me with solid-app-router. This is not the only route design, I also tried the configuration/array based route design as well and had the same problem. I'm open to suggestions for how to properly implement this functionality.
As the other commenter said, my code for the fallback route actually does work. This was a reactivity issue.
When the page first loads, isAuthenticated() returns false, because the authentication check is an ajax call that hadn't run yet. Therefore the /categories route wouldn't be rendered, and if I was trying to manually navigate to /categories I would instead by redirected. This made it appear as though the catch-all route was overriding everything, when in fact it was behaving as expected.
I added another check to prevent the routes from rendering until after the authentication check ajax call was made, and then everything worked perfectly.

How to pass data between pages without URL Parameters

I'm wondering how I can pass non-string data between two pages in Ionic 5 using ReactRouter.
All solutions I could find used Ionic and Angular or just passed one string as URL parameter.
These are my components so far:
App.tsx
const App: React.FC = () => {
return (
<IonApp>
<IonReactRouter>
<IonSplitPane contentId="main">
<Menu />
<IonRouterOutlet id="main">
<Route path="/page/Home" component={Home} exact />
<Route path="/page/DataEntry" component={DataEntry} exact />
<Route path="/page/Request" component={Request} exact />
<Route path="/page/ResultMap" component={ResultMap} exact />
<Redirect from="/" to="/page/Home" exact />
</IonRouterOutlet>
</IonSplitPane>
</IonReactRouter>
</IonApp>
);
};
Page 1 here collects user input data (strings, objects, arrays) and I want to call the route '/page/ResultMap' on Button click and pass the data, so the next page can handle it:
<IonGrid>
<IonRow>
<IonCol class="ion-text-center">
<IonButton text-center="ion-text-center" color="primary" size="default" routerLink='/page/ResultMap'>Erkunden!</IonButton>
</IonCol>
</IonRow>
</IonGrid>
Page 2, which should receive the Data:
const ResultMap: React.FC = () => {
return (
<IonPage>
<IonHeader>
<IonToolbar>
<IonButtons slot="start">
<IonMenuButton />
</IonButtons>
<IonTitle>Map</IonTitle>
</IonToolbar>
</IonHeader>
<IonContent fullscreen>
</IonContent>
</IonPage>
);
};
I understand the React principle about props and state, I just dont know how to combine it with Ionic in this case.
I appreciate your help!
Edit:
As suggested I changed the button onClick like this:
<IonButton text-center="ion-text-center" color="primary" size="default" onClick={e => {
e.preventDefault();
history.push({
pathname: '/page/ResultMap',
state: { time: transportTime }
})}}>
And try to receive the data on the ResultMap page like this:
let time = history.location.state.time;
But I get the error:
Object is of type 'unknown'. TS2571
7 | let history = useHistory();
8 |
> 9 | let time = history.location.state.time;
| ^
How do I access the passed object on the new page?
as for react-router I know you can use this:
history.push({
pathname: '/template',
state: { detail: response.data }
})
in this situation you can pass data without URL Params
can also use history.replace
if you redirect and want the back button work properly to the end user
and for the history do the following
let history = useHistory();
Check this link for a great understand how to implement the useHistory type

Getting a dialog on click of Edit Button on admin-on-rest

I am working on an application using admin-on-rest framework. For editing an entry on a Resource we provide XXXEdit, XXXShow, XXXCreate props to it. My requirement is that when I click on an Edit button in List view on any entry I should get a Dialog box with the parameters in XXXEdit instead of going to a new page. I tried doing this by using a Dialog in XXXEdit component
<Edit title={<RoleTitle />} {...props}>
<SimpleForm>
<Dialog
title="Dialog With Actions"
actions={actions}
modal={false}
open={true}
>
<TextInput source="id" />
<TextInput source="name" validate={required} />
.
.//some more fields
</Dialog>
</SimpleForm>
</Edit>
I get errors like The TextInput component wasn't called within a redux-form
If I use a DisabledInput then I get an error cannot read value of undefined
How do I go on with this?
I do not think you can use Simpleform for this. You will need to create a custom Form using Redux-Form. Look at the bottom answer that documents the final answer.
This might help you
How to richly style AOR Edit page
Instead of creating a page. You are creating a component that connects to the Redux state and displays as a dialog box.
I tried to resolve this using HOC and react-router.
I created a button using AOR button and provided a containerElement
containerElement={
<Link
key={record.id}
to={{
...{
pathname: `${basePath}/${encodeURIComponent(record.id)}`
},
...{ state: { modal: true } }
}}
/>
}
I created a route like this where DialogRoleEdit is an AOR edit component wrapped with a dialog HOC below .
<Route
exact
path="/roles/:id"
render={routeProps => {
return !!(
routeProps.location.state && routeProps.location.state.modal
) ? (
<Restricted authClient={authClient} location={routeProps.location}>
<div>
<RoleList resource={"roles"} {...routeProps} />
<DialogRoleEdit resource={"roles"} {...routeProps} />
</div>
</Restricted>
) : (
<Restricted authClient={authClient} location={routeProps.location}>
<RoleEdit resource={"roles"} {...routeProps} />
</Restricted>
);
}}
/>
Finally an HOC
handleClose = () => {
this.props.history.goBack();
};
render() {
const actions = [
<FlatButton label="Cancel" primary={true} onClick={this.handleClose} />
];
return (
<Dialog>
<WrappedComponent/>
</Dialog>
)
}
We need to provide edit prop for this resource in App.js
edit={DialogUserEdit}

React-router redirect is looping over components in Meteorjs

I am experimenting on custom admin view page and do have one question about the behavior.
The current logic at the moment is:
If the user in not authenticated and tries to visit /admin-panel or its children he/she gets redirected to /& login page.
If user in logged in and visits /& (login page) he/she gets redirected to /admin-panel
The problem is when the user is lodded in and is on /admin-panel and reloads the page the following occurs:
First /& page loads
Then /& redirects user to /admin-panel
If the user was on or /admin-panel/child_component after reload he/she will be on /admin-panel and will have to navigate again to /child_component
Can you please explain what is the cause of current behavior and if there is some way to make user stay on the page the reload was initiated and can the constant redirection be avoided?
The login page /&
import React, { Component } from 'react';
import { Link, browserHistory } from 'react-router';
import { Tracker } from 'meteor/tracker'
class Backdoor extends Component {
onSubmit(event) {
event.preventDefault();
// Collecting user input
const self = this;
const email = $(event.target).find('[name=email]').val();
const password = $(event.target).find('[name=password]').val();
Meteor.loginWithPassword(email, password, function (err) {
browserHistory.push('admin-panel');
});
}
componentWillMount(){
Tracker.autorun(() => {
if (Meteor.user()) {
browserHistory.push('/admin-panel')
} else if(!Meteor.user()) {
browserHistory.push('/&')
}
})
}
render() {
return (
// Login form
);
}
}
export default Backdoor;
React-router paths':
const routes = (
<Router history={browserHistory}>
<Route path='/' component={App}>
<Router path='about' component={About} />
</Route>
<Route path='&' component={Backdoor} />
<Route path='admin' component={AdminPanel}>
<Router path='/admin/admin_component' component={AdminChild} />
</Route>
</Router>
I would change your routes file in the following way:
const routes = (
<Router history={browserHistory}>
<Route path='/' component={App}>
<Route path='about' component={About} />
<Route path='&' component={Backdoor} />
<Route path='admin' component={Admin} />
<Route path='admin/admin_component' component={AdminChild} />
<Route path='admin/admin_panel' component={AdminPanel} />
</Route>
</Router>
);
So we got rid of the nested "Router" components that you had in there and added a "AdminPanel" component.
One of the things I usually do is assign an IndexRoute to my apps. You can look that up and it might provides some benefit, I didn't add it in since you didn't have it in your code.
Another efficiency (IMO) is to nest your admin routes as such:
const routes = (
<Router history={browserHistory}>
<Route path='/' component={App}>
<Router path='about' component={About} />
<Route path='&' component={Backdoor} />
<Route path='admin' component={Admin}>
<Route path='/admin_component' component={AdminChild} />
<Route path='/admin_panel' component={AdminPanel} />
</Route>
</Route>
</Router>
);
Note that the admin panel is nested in the admin route so to get there it would be /admin/admin_panel. Also, I would use "" quotes instead of ''.
First of all I've got rid of /& route and now the Admin Authentication routes look like that:
const newRoutes = (
<Router history={browserHistory}>
<Route path='/' component={App}>
<Router path='about' component={About} />
</Route>
<Route path='/admin' component={Admin} >
<Route path='/admin/admin_child' component={AdminChild} />\
// Feel free to add more routes here
</Route>
</Router>
);
So inside the admin route you define if statement for checking if user is logged in. The hole component looks like that:
export class Admin extends Component {
componentWillMount(){
Tracker.autorun(() => {
if(!Meteor.userId()) {
browserHistory.push('/admin')
}
})
}
render(props) {
if (Meteor.userId()){
return (<div><JuliaNav />{this.props.children}</div>)
} else {
return (<div><Backdoor /></div>)
}
}
}
So if the admin is not logged in React returns log-in form, and if he/she is logged in the component returns AdminNavigation for further interaction with data.
Tracker checks the state of user and if the button Log Off (inside AdminNavigation) will be clicked the page will be reloaded (with browserHistory.push) and AdminNavigation component will be replaced with the log-in form.