I use this method to show private pages to the user. The problem is that no page is displayed to me, but the logs that I put in PrivatePage
work properly.
Components
are correct because when I simply call the routes, the components are returned correctly but it has a problem with PrivatePage
and does nothing.
function Auth() {
return new Promise((resolve, reject) => {
let appData = GetAppData();
if (appData.UserToken.length == 0) {
reject(-2);
}
let request = {
Token: appData.UserToken,
UserId: appData.UserId
}
axios.post("****UserValidUrl****", request).then(response => {
switch (response.data.Type) {
case 10:
resolve(10);
break;
case -2:
reject(-2);
break;
case -13:
reject(-13);
}
}).catch(err => {
reject(-13);
})
})
}
const PrivatePage = ({children, ...rest}) => (
return <Route
{...rest}
render={async ({location }) => {
let type = 10;
try {
type = await Auth();
} catch(e) {
type = -13;
}
Log(type);
switch (type) {
case 10:
return children;
break
case -2:
return (
<Redirect
to={{
pathname: '/Auth/Login',
state: { from: location },
}}
/>)
case -13:
return (
<Redirect
to={{
pathname: '/NotFound',
state: { from: location },
}}
/>)
break;
}}
}/>
)
export default function BasePage() {
return (
<div>
<BrowserRouter>
<Switch>
<Route exact path={"/Auth/Login"} component={Login}/>
<PrivatePage path={"/"}>
<Switch>
<Route exact path={"/"} component={Home}/>
<Route exact path={"/Dashboard/Home"} component={Home}/>
<Route exact path={"/Dashboard/Profile"} component={Profile}/>
<Route component={NotFound}/>
</Switch>
}/>
</Switch>
</BrowserRouter>
</div>
);
}
Error Text:
Error: Objects are not valid as a React child (found: [object Promise]). If you meant to render a collection of children, use an array instead.
CodePudding user response:
Maybe you can do something like this in your private route.
PrivatePage
const PrivatePage = ({ children, ...rest }) => (
<Route
{...rest}
render={async ({ location }) => {
let isAuthenticated = false;
try {
isAuthenticated = await Auth();
} catch(e) {
// If you want to log the error.
}
if (isAuthenticated) {
return children;
}
return (
<Redirect
to={{
pathname: '/login',
state: { from: location },
}}
/>
);
}}
/>
);
BasePage
export default function BasePage() {
return (
<div>
<BrowserRouter>
<Switch>
<Route exact path={"/Auth/Login"} component={Login}/>
<PrivatePage path={"/"}>
<Switch>
<Route exact path={"/"} component={Home}/>
<Route exact path={"/Dashboard/Home"} component={Home}/>
<Route exact path={"/Dashboard/Profile"} component={Profile}/>
<Route component={NotFound}/>
</Switch>
</PrivatePage>
</Switch>
</BrowserRouter>
</div>
);
}
EDIT
PrivatePage for specific numeric value in Auth.
const PrivatePage = ({children, ...rest}) => (
return <Route
{...rest}
render={async ({location }) => {
let authenticated = false;
try {
authenticated = await Auth();
} catch(e) {
// If you want to log the error.
}
if(authenticated === -2) {
// redirect one
} else if (authenticated === -13) {
// redirect two
} if (authenticated) {
return children;
}
return (
<Redirect
to={{
pathname: "/Auth/Login",
state: { from: location },
}}
/>
);
}}
/>
)
CodePudding user response:
Your navigation looks complex for authentication. you can treat your component as route and do routing as this.
Assuming that you have authenticated separately and you just check if it's good to go, instead of trying to authenticate every single time for route. If you prefer this authentication on route, still solution applies.
function AuthenticatedRoute({ children, ...props }) {
const isAuthenticated = useContext(AuthenticationContext);
return isAuthenticated ? (
<Route {...props}>{children}</Route>
) : (
<Redirect
to={{
pathname: '/login',
state: { from: location },
}}
/>
);
}
and use it like:
<AuthenticatedRoute path="/Dashboard/Home" exact>
<h1>Hey Doctor Strange! You made it</h1>
</AuthenticatedRoute>
I also have created a protected auth routing in this code sandbox for reference: https://codesandbox.io/s/cranky-poincare-l2c06?file=/src/App.js:262-488