Let's say I have these routes:
<Switch>
<Route exact path="/myflix/:slug" component={Home} />
<Route exact path="/myflix/:slug/register" component={Signup} />
<Route exact path="/myflix/:slug/event" component={Event} />
<Route exact path="/myflix/:slug/contact" component={Contact} />
<Route exact path="/myflix/:slug/login" component={Login} />
<Route exact path="/myflix/:slug/show-details" component={ShowList} />
<Route exact path="/myflix/:slug/*" component={NotFound} />
<Route path="*" exact={true} component={NotFound} />
<Redirect to="/not-found" />
{/* <Route path="*" element={<NotFound />} /> */}
</Switch>
We have certain slugs from an API, in this form:
[
{
id: 1,
title: "_flix",
slug: "_flix",
status: true,
viewTime: null,
langue: null,
createdAt: "2021-06-24",
updatedAt: null,
},
{
id: 9,
title: "test_flix",
slug: "test_flix",
status: true,
viewTime: null,
langue: null,
createdAt: "2021-06-24",
updatedAt: null,
},
{
id: 10,
title: "flix_2",
slug: "flix_2",
status: true,
viewTime: null,
langue: null,
createdAt: "2021-06-24",
updatedAt: null,
},
]
When I make an invalid slug, I want to redirect to NotFound page:
useEffect(() => {
getSlug(slug)
.then((res) => {
const { id } = res.data;
document.title = res.data.title;
getSetting(id).then((result) => {
setStyle(result.data);
getLangue(id).then((res) => {
setlang(res.data.langue);
});
});
})
.catch((error) => (window.location.href = "/not-found"));
}, [slug]);
I used the above code (see the .catch), but when I make an invalid slug, it redirects not found page and refresh the page. I need to redirect without refreshing. Any solution?
window.location.href does indeed refresh the page. Since you seem to be using React Router Dom v5, you should be using useHistory to make redirections. Here is an overview of how you would use it:
import { useHistory } from "react-router-dom";
function HomeButton() {
let history = useHistory();
function handleClick() {
history.push("/home");
}
return (
<button type="button" onClick={handleClick}>
Go home
</button>
);
}
Not related to useHistory or the redirection, but you could optimise slightly your routes setup:
<Switch>
<Route exact path="/myflix/:slug" component={Home} />
<Route exact path="/myflix/:slug/register" component={Signup} />
<Route exact path="/myflix/:slug/event" component={Event} />
<Route exact path="/myflix/:slug/contact" component={Contact} />
<Route exact path="/myflix/:slug/login" component={Login} />
<Route exact path="/myflix/:slug/show-details" component={ShowList} />
<Route path="*" component={NotFound} />
</Switch>
Using window.location.href = "/not-found" mutates the current location and reloads the page, i.e. it will remount the entire React app. Use an imperative redirect to the "/not-found" route.
import { useHistory } from 'react-router-dom';
...
const history = useHistory();
...
useEffect(() => {
getSlug(slug)
.then((res) => {
const { id, title } = res.data;
document.title = title;
getSetting(id)
.then((result) => {
setStyle(result.data);
});
getLangue(id)
.then((res) => {
setLang(res.data.langue);
});
})
.catch((error) => {
history.replace("/not-found"); // REPLACE = redirect
});
}, [slug]);
Render a Route on path="/not-found" that can be redirected to.
<Switch>
<Route path="/myflix/:slug/register" component={Signup} />
<Route path="/myflix/:slug/event" component={Event} />
<Route path="/myflix/:slug/contact" component={Contact} />
<Route path="/myflix/:slug/login" component={Login} />
<Route path="/myflix/:slug/show-details" component={ShowList} />
<Redirect from="/myflix/:slug/*" to="/not-found" /> // <-- redirect unhandled paths
<Route path="/myflix/:slug" component={Home} />
<Route path="/not-found" component={NotFound} /> // <-- render NotFound component route
<Redirect to="/not-found" />
</Switch>