I am new in ReactJS and starting my first app with React. I've been watching videos and going through various tutorials and finally managed to scaffold my first ReactRedux app with Login.
I've used AuthWorkflow example of ReactTraining website. There they used a PrivateRoute
component to secure protected routes. I've implemented it and its working.
Problem:
Now I can't send any custom data or like user data to protected route. How can I sent it?
Code
import React from "react";
import {
BrowserRouter as Router,
Route,
Link,
Redirect,
withRouter
} from "react-router-dom";
////////////////////////////////////////////////////////////
// 1. Click the public page
// 2. Click the protected page
// 3. Log in
// 4. Click the back button, note the URL each time
const AuthExample = () => (
<Router>
<div>
<AuthButton />
<ul>
<li>
<Link to="/public">Public Page</Link>
</li>
<li>
<Link to="/protected">Protected Page</Link>
</li>
</ul>
<Route path="/public" component={Public} />
<Route path="/login" component={Login} />
// Here I want to pass the user data to protected component.
<PrivateRoute path="/protected" component={Protected} user={username:'ariful', email:'[email protected]'}/>
</div>
</Router>
);
const fakeAuth = {
isAuthenticated: false,
authenticate(cb) {
this.isAuthenticated = true;
setTimeout(cb, 100); // fake async
},
signout(cb) {
this.isAuthenticated = false;
setTimeout(cb, 100);
}
};
const AuthButton = withRouter(
({ history }) =>
fakeAuth.isAuthenticated ? (
<p>
Welcome!{" "}
<button
onClick={() => {
fakeAuth.signout(() => history.push("/"));
}}
>
Sign out
</button>
</p>
) : (
<p>You are not logged in.</p>
)
);
const PrivateRoute = ({ component: Component, ...rest }) => (
<Route
{...rest}
render={props =>
fakeAuth.isAuthenticated ? (
<Component {...props} />
) : (
<Redirect
to={{
pathname: "/login",
state: { from: props.location }
}}
/>
)
}
/>
);
const Public = () => <h3>Public</h3>;
// show the username here
const Protected = (props) => <h3>Protected Username: {props.user.username}</h3>;
class Login extends React.Component {
state = {
redirectToReferrer: false
};
login = () => {
fakeAuth.authenticate(() => {
this.setState({ redirectToReferrer: true });
});
};
render() {
const { from } = this.props.location.state || { from: { pathname: "/" } };
const { redirectToReferrer } = this.state;
if (redirectToReferrer) {
return <Redirect to={from} />;
}
return (
<div>
<p>You must log in to view the page at {from.pathname}</p>
<button onClick={this.login}>Log in</button>
</div>
);
}
}
export default AuthExample;
How can I successfully send the user object to protected component?
You need to pass on the ...rest
params that you pass to PrivateRoute
on to the component, however not all of them need to react the component. You can destructure other params that are needed by React router
const PrivateRoute = ({ component: Component, exact, strict, path, ...rest }) => (
<Route
exact={exact}
strict={strict}
path={path}
render={props =>
fakeAuth.isAuthenticated ? (
<Component {...props} {...rest} />
) : (
<Redirect
to={{
pathname: "/login",
state: { from: props.location }
}}
/>
)
}
/>
);
See where the issue is:
<PrivateRoute
path="/protected"
component={Protected}
user={username:'ariful', email:'[email protected]'} />
Now inside PrivateRoute
component, user object will get passed as props, it will be available in rest
object, also rest
will have the data that will be required for Route
, so to make it more generic.
Instead of passing the user object always pass data
, now rest will have the data required for Route and data will be the data passed to component, write it like this:
const PrivateRoute = ({ component: Component, data, ...rest }) => (
<Route
{...rest}
render={props =>
fakeAuth.isAuthenticated ? (
<Component {...props} {...data} />
) : (
<Redirect
to={{
pathname: "/login",
state: { from: props.location }
}}
/>
)
}
/>
);
Pass that data to <Component {...data} {...props} />
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With