Reputation: 112
I'm taring authentication in React using Laravel API and everything works perfectly except for some router problems.
I'm conditionally rendering a redirect like this:
if (this.state.redirect) {
return <Redirect to="/home" />;
}
const login = localStorage.getItem("isLoggedIn");
if (login) {
return <Redirect to="/home" />;
}
App.js
export default class App extends Component {
render() {
let navLink = (
<div className="Tab">
<NavLink to="/sign-in" activeClassName="activeLink" className="signIn">
Sign In
</NavLink>
<NavLink exact to="/" activeClassName="activeLink" className="signUp">
Sign Up
</NavLink>
</div>
);
const login = localStorage.getItem("isLoggedIn");
return (
<div className="App">
{login ? (
<Router>
<Route exact path="/" component={Signup}></Route>
<Route path="/sign-in" component={Signin}></Route>
<Route path="/home" component={Home}></Route>
</Router>
) : (
<Router>
{navLink}
<Route exact path="/" component={Signup}></Route>
<Route path="/sign-in" component={Signin}></Route>
<Route path="/home" component={Home}></Route>
</Router>
)}
</div>
);
}
}
Signin.js
export default class Signin extends Component {
constructor(props) {
super(props);
this.state = {
email: "",
password: "",
msg: "",
isLoading: false,
redirect: false,
errMsgEmail: "",
errMsgPwd: "",
errMsg: "",
};
}
onChangehandler = (e) => {
let name = e.target.name;
let value = e.target.value;
let data = {};
data[name] = value;
this.setState(data);
};
onSignInHandler = () => {
this.setState({ isLoading: true });
axios
.post("http://localhost:8000/api/user-login", {
email: this.state.email,
password: this.state.password,
})
.then((response) => {
this.setState({ isLoading: false });
if (response.data.status === 200) {
localStorage.setItem("isLoggedIn", true);
localStorage.setItem("userData", JSON.stringify(response.data.data));
this.setState({
msg: response.data.message,
redirect: true,
});
}
if (
response.data.status === "failed" &&
response.data.success === undefined
) {
this.setState({
errMsgEmail: response.data.validation_error.email,
errMsgPwd: response.data.validation_error.password,
});
setTimeout(() => {
this.setState({ errMsgEmail: "", errMsgPwd: "" });
}, 2000);
} else if (
response.data.status === "failed" &&
response.data.success === false
) {
this.setState({
errMsg: response.data.message,
});
setTimeout(() => {
this.setState({ errMsg: "" });
}, 2000);
}
})
.catch((error) => {
console.log(error);
});
};
render() {
if (this.state.redirect) {
return <Redirect to="/home" />;
}
const login = localStorage.getItem("isLoggedIn");
if (login) {
return <Redirect to="/home" />;
}
const isLoading = this.state.isLoading;
return (
<div>
<Form className="containers">
<FormGroup>
<Label for="email">Email id</Label>
<Input
type="email"
name="email"
placeholder="Enter email"
value={this.state.email}
onChange={this.onChangehandler}
/>
<span className="text-danger">{this.state.msg}</span>
<span className="text-danger">{this.state.errMsgEmail}</span>
</FormGroup>
<FormGroup>
<Label for="password">Password</Label>
<Input
type="password"
name="password"
placeholder="Enter password"
value={this.state.password}
onChange={this.onChangehandler}
/>
<span className="text-danger">{this.state.errMsgPwd}</span>
</FormGroup>
<p className="text-danger">{this.state.errMsg}</p>
<Button
className="text-center mb-4"
color="success"
onClick={this.onSignInHandler}
>
Sign In
{isLoading ? (
<span
className="spinner-border spinner-border-sm ml-5"
role="status"
aria-hidden="true"
></span>
) : (
<span></span>
)}
</Button>
</Form>
</div>
);
}
}
Signup.js
export default class Signup extends Component {
userData;
constructor(props) {
super(props);
this.state = {
signupData: {
name: "",
email: "",
phone: "",
password: "",
isLoading: "",
},
msg: "",
};
}
onChangehandler = (e, key) => {
const { signupData } = this.state;
signupData[e.target.name] = e.target.value;
this.setState({ signupData });
};
onSubmitHandler = (e) => {
e.preventDefault();
this.setState({ isLoading: true });
axios
.post("http://localhost:8000/api/user-signup", this.state.signupData)
.then((response) => {
this.setState({ isLoading: false });
if (response.data.status === 200) {
this.setState({
msg: response.data.message,
signupData: {
name: "",
email: "",
phone: "",
password: "",
},
});
setTimeout(() => {
this.setState({ msg: "" });
}, 2000);
}
if (response.data.status === "failed") {
this.setState({ msg: response.data.message });
setTimeout(() => {
this.setState({ msg: "" });
}, 2000);
}
});
};
render() {
const isLoading = this.state.isLoading;
return (
<div>
<Form className="containers shadow">
<FormGroup>
<Label for="name">Name</Label>
<Input
type="name"
name="name"
placeholder="Enter name"
value={this.state.signupData.name}
onChange={this.onChangehandler}
/>
</FormGroup>
<FormGroup>
<Label for="email">Email id</Label>
<Input
type="email"
name="email"
placeholder="Enter email"
value={this.state.signupData.email}
onChange={this.onChangehandler}
/>
</FormGroup>
<FormGroup>
<Label for="phone">Phone Number</Label>
<Input
type="phone"
name="phone"
placeholder="Enter phone number"
value={this.state.signupData.phone}
onChange={this.onChangehandler}
/>
</FormGroup>
<FormGroup>
<Label for="password">Password</Label>
<Input
type="password"
name="password"
placeholder="Enter password"
value={this.state.signupData.password}
onChange={this.onChangehandler}
/>
</FormGroup>
<p className="text-white">{this.state.msg}</p>
<Button
className="text-center mb-4"
color="success"
onClick={this.onSubmitHandler}
>
Sign Up
{isLoading ? (
<span
className="spinner-border spinner-border-sm ml-5"
role="status"
aria-hidden="true"
></span>
) : (
<span></span>
)}
</Button>
<Link to="/sign-in" className="text-white ml-5">I'm already member</Link>
</Form>
</div>
);
}
}
My problem is that the {navLink} component still rendered in both cases logged in or not!! but when I refresh the page manually it goes!
Upvotes: 1
Views: 224
Reputation: 4528
I have some experience on this, so ill share it for you maybe helps you.
Make a protected root
export const ProtectedRoute = (props) => {
let redirectPath = "";
if (!localStorage.getItem("isLoggedIn")) {
redirectPath = props.authenticationPath;
}
if (redirectPath) {
const renderComponent = () => <Redirect to={{ pathname: redirectPath }} />;
return <Route {...props} component={renderComponent} render={undefined} />;
} else {
return <Route {...props} />;
}
};
Use it like this on router component :
<ProtectedRoute
exact
path="/profile"
component={Profile}
restrictedPath="/profile"
authenticationPath="/login"
/>
After submit login form or signup form
history.push("/profile")
I did make Small example on codesandbox with all of you need for start, Hope it helps.
Upvotes: 2