The technology stack I use is React TS React-Router-V6 Now the page will pass parameters after clicking the button, and the page can change in real time and receive the parameters passed (as shown in the figure below).
But I hope I can achieve the same effect as the following picture, the page will be re-rendered after clicking. I used useEffect to capture id parameters, but there was no effect, what should I do to achieve the same effect as the following picture
The parameter of my route parameter is id. The route is defined as follows.
const routes: RouteObject[] = [
{ path: "/", element: <Navigate to="/discover" /> },
{
path: "/discover",
element: <Discover />,
children: [
{ path: "/discover", element: <Navigate to="/discover/recommend" /> },
{ path: "/discover/recommend", element: <Recommend /> },
{ path: "/discover/ranking", element: <Ranking /> },
{ path: "/discover/singers", element: <Singers /> },
{ path: "/discover/songs", element: <Songs /> },
{ path: "/discover/album", element: <Album /> },
{
path: "/discover/djradio",
element: <DJRadio />,
children: [
{ path: "/discover/djradio/category", element: <Category /> },
],
},
],
},
{ path: "/mine", element: <Mine /> },
{ path: "/focus", element: <Focus /> },
{ path: "/download", element: <Download /> },
];
export default routes;
Here is the code for my component
import { Carousel } from "antd";
import React, { ReactNode, useEffect, useRef, memo, ElementRef } from "react";
import { Outlet, useNavigate } from "react-router-dom";
import { getRadioDataAction } from "./store";
import { useBearDispatch, useBearSelector } from "@/store";
import { RadioWrapper } from "./style";
import { RadioItemWrapper } from "./style";
import classNames from "classnames";
import { useQuery } from "@/utils/useQuery";
interface IProps {
children?: ReactNode;
}
const DJRadio: React.FC<IProps> = () => {
const dispatch = useBearDispatch();
const ref = useRef<ElementRef<typeof Carousel>>(null);
const navigate = useNavigate();
const { id } = useQuery();
const currentID = id;
const { catelist } = useBearSelector((state) => ({
catelist: state.radio.catelist,
}));
useEffect(() => {
dispatch(getRadioDataAction());
}, [id]);
function handleChange(isNext: boolean) {
if (isNext) {
ref.current?.next();
} else {
ref.current?.prev();
}
}
function handleClickTo(id: number) {
const wantUrl = "/discover/djradio/category?id=" id;
navigate(wantUrl);
}
return (
<RadioWrapper className="all-bg">
<div className="wrap-v2 content">
<div className="content-top">
<div
className="my-left sprite-dj-btn"
onClick={() => {
handleChange(false);
}}
></div>
<Carousel className="carousel" ref={ref}>
{[0, 1].map((item: any, index: number) => {
return (
<div className="dj-content" key={index}>
{catelist &&
catelist
.slice(index * 18, (index 1) * 18)
.map((element: any) => {
return (
<RadioItemWrapper
key={element.id}
imgUrl={element.picWebUrl}
onClick={() => handleClickTo(element.id)}
className={classNames({
active: currentID == element.id,
})}
>
<div className="img-content">
<div className="item-img"></div>
</div>
<span className="item-name">{element.name}</span>
</RadioItemWrapper>
);
})}
</div>
);
})}
</Carousel>
<div
className="my-right sprite-dj-btn"
onClick={() => {
handleChange(true);
}}
></div>
</div>
<div>{id}</div>
<Outlet></Outlet>
</div>
</RadioWrapper>
);
};
export default memo(DJRadio);
a page reloads after a route parameter is passed
CodePudding user response:
I just want a reload effect. useEffect does not rerender when used.
The useEffect
is run as the result of the component having been rendered; it doesn't itself cause any rerenders or page reloads.
A trivial solution to "reload" the "/discover/djradio/category"
page would be to call window.location.reload
from a useEffect
hook in Category
when the id
queryString parameter value changes.
Example:
import { useSearchParams } from 'react-router-dom';
const Category = () => {
const [searchParams] = useSearchParams();
const id = searchParams.get("id");
React.useEffect(() => {
window.location.reload();
}, [id]);
...
};
This would actually make a network request to the server for the page/react app and might not be ideal. You could fake a reload with some state that just conditionally renders null for a second or to and then switches back to the Category
UI JSX.
Example:
import { useSearchParams } from 'react-router-dom';
const Category = () => {
const [searchParams] = useSearchParams();
const [loading, setLoading] = React.useState(true);
const id = searchParams.get("id");
React.useEffect(() => {
setLoading(true);
const timer = setTimeout(() => {
setLoading(false);
}, 3000);
return () => {
clearTimeout(timer);
};
}, [id]);
...
if (loading) {
return null; // or loading indicator/spinner/etc...
}
...
};