【问题标题】:What does React do when a page reloads after a route parameter is passed?传递路由参数后页面重新加载时,React 会做什么?
【发布时间】:2023-01-12 10:15:41
【问题描述】:

我使用的技术栈是React+TS+React-Router-V6 现在点击按钮后页面会传递参数,页面可以实时变化并接收传递的参数(如下图)。

enter image description here

但我希望能达到下图一样的效果,点击后页面会重新渲染。我用useEffect捕获id参数,但是没有效果,应该怎么做才能达到下图一样的效果

我的路由参数的参数是id。路由定义如下。

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

这是我的组件的代码

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

传递路由参数后页面重新加载

【问题讨论】:

  • 抱歉,也许这是语言障碍,但动画屏幕 gif 并没有说清楚你到底想展示什么。没有看到您的路线声明,也不清楚您指的是什么路线参数。你可以 edit 帖子来澄清你想做什么吗?
  • 嗨,我想在路由参数 (id) 后重新渲染(如刷新)第二张图像。
  • 什么需要重新渲染或刷新?什么会触发这个?我没有看到任何带参数的路由。您指的是 URL queryString 参数,特别是 id 查询参数吗?据我对您的代码的了解,它已经是 useEffect 挂钩的依赖项。当您使用新的 idqueryString 参数值导航时,组件是否没有按预期重新呈现?
  • 现在当我点击每个按钮时,参数 id 将传递给路由。我希望点击每个按钮后页面都会刷新(如图2),但是我现在点击没有这样的效果。
  • 好的,是的,id 不是react-router 关心的任何东西,因为它不是任何路由路径的一部分。 id 查询参数更改时有什么问题? useEffect 钩子没有被触发?这是 useQuery 钩子从 queryString 读取 id 吗?您可以将该代码添加到您的帖子中吗?

标签: javascript reactjs typescript react-hooks react-router-dom


【解决方案1】:

我只想要一个重载效果。 useEffect 在使用时不会重新渲染。

useEffect 作为组件渲染的结果运行;它本身不会导致任何重新呈现或页面重新加载。

“重新加载”"/discover/djradio/category" 页面的一个简单解决方案是当 id queryString 参数值更改时,从 Category 中的 useEffect 挂钩调用 window.location.reload

例子:

import { useSearchParams } from 'react-router-dom';

const Category = () => {
  const [searchParams] = useSearchParams();
  const id = searchParams.get("id");

  React.useEffect(() => {
    window.location.reload();
  }, [id]);

  ...
};

这实际上会向服务器发出页面/反应应用程序的网络请求,可能并不理想。您可以使用某些状态伪造重新加载,该状态只是有条件地呈现 null 一秒钟或到然后切换回 Category UI JSX。

例子:

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

  ...
};

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2019-01-16
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-01-17
    • 2020-09-19
    • 1970-01-01
    相关资源
    最近更新 更多