Home > Mobile >  What does React do when a page reloads after a route parameter is passed?
What does React do when a page reloads after a route parameter is passed?

Time:01-12

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).

enter image description here

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;

enter image description here

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...
  }

  ...
};
  • Related