我是个新手,正在按照一个教程来训练自己.

我遇到的问题是,我有几条路由用不同的props 渲染相同的组件,但使用NavLink导航时,该组件似乎没有被挂载/卸载.所以我的定制钩子没有被触发,就好像我们还没有导航一样.

如果我在导航后手动刷新页面,组件将正确更新. 我用react@18.2.0react-router-dom@6.16.0.

  • index.tsx
    import React from 'react';
    import ReactDOM from 'react-dom/client';
    import { BrowserRouter } from "react-router-dom";
    import './index.css';
    import App from './App';
    
    const root = ReactDOM.createRoot(
      document.getElementById('root') as HTMLElement
    );
    root.render(
      <React.StrictMode>
        <BrowserRouter>
          <App />
        </BrowserRouter>
      </React.StrictMode>
    );
    
  • App.tsx
    import React from 'react';
    import { Header } from "./components";
    import { Route, Routes } from "react-router-dom";
    import { MovieList } from "./pages";
    
    function App() {
      return (
        <>
          <Header />
          <Routes>
            <Route path="/" element={<MovieList />} />
            <Route path="/movies/bottom" element={<MovieList sort='bottom' />} />
            <Route path="/movies/unpopular" element={<MovieList sort='unpopular' />} />
            <Route path="/movies/upcoming" element={<MovieList sort='upcoming' />} />
          </Routes>
        </>
      );
    }
    
    export default App;
    
  • Header.tsx的组成部分中,我有:
    <li>
      <NavLink to="/" className={linkClass} aria-current="page" end>Recent</NavLink>
    </li>
    <li>
      <NavLink to="/movies/unpopular" className={linkClass}>Unpopular</NavLink>
    </li>
    <li>
      <NavLink to="/movies/bottom" className={linkClass}>Bottom Rated</NavLink>
    </li>
    <li>
      <NavLink to="/movies/upcoming" className={linkClass}>Upcoming</NavLink>
    </li>
    
  • MovieList.tsx
    import { useState } from "react";
    import { Card } from "../components";
    import { MovieService } from "../services/Movie.service";
    
    type MovieListProps = {
      sort?: MovieService.defaultSort;
    }
    
    export function MovieList({ sort }: MovieListProps = {}) {
      const [filter, setFilter] = useState({
        defaultSort: sort
      });
      const movies = MovieService.useGet(filter);
    
      return (
        <main>
          <button onClick={() => setFilter({defaultSort: 'now_playing'})}>Recent</button>
          <button onClick={() => setFilter({defaultSort: 'unpopular'})}>unpopular</button>
          <button onClick={() => setFilter({defaultSort: 'bottom'})}>Bottom Ratted</button>
          <button onClick={() => setFilter({defaultSort: 'upcoming'})}>Upcoming</button>
          <section className="flex flex-wrap justify-center gap-4">
            {
              movies.data?.results.map((movie, index) => (
                <Card key={index} item={movie}/>
              ))
            }
          </section>
        </main>
      );
    }
    

在这里,当我单击标题中的NavLink时,movies对象不会更新,但我添加了一些调用setFilter的按钮,当我单击这些按钮时,它工作得很好,为什么?

您可以在此处找到该教程的代码:github

我之所以有不同之处,是因为我使用的是TypeScrip,并且我分离了代码以不同的方式获取API,您可以在这里找到我当前的代码:github

但我仍然不明白为什么我的实现不起作用.

推荐答案

Reaction-路由进行优化,以保持Reaction组件的挂载.换句话说,它尽量不做任何额外的工作来卸载和重新挂载相同的Reaction组件,如果它可以帮助它的话.在Reaction中,触发组件重现器比重新挂载更省力.

您可以添加useEffect挂钩,以在sortprops 值更改时更新filter状态:

export function MovieList({ sort }: MovieListProps = {}) {
  const [filter, setFilter] = useState({ defaultSort: sort });

  useEffect(() => {
    setfilter({ defaultSort: sort });
  }, [sort]);

  const movies = MovieService.useGet(filter);

  return (
    <main>
      <button onClick={() => setFilter({ defaultSort: 'now_playing' })}>
        Recent
      </button>
      <button onClick={() => setFilter({ defaultSort: 'unpopular' })}>
        unpopular
      </button>
      <button onClick={() => setFilter({ defaultSort: 'bottom' })}>
        Bottom Ratted
      </button>
      <button onClick={() => setFilter({ defaultSort: 'upcoming' })}>
        Upcoming
      </button>
      <section className="flex flex-wrap justify-center gap-4">
        {movies.data?.results.map((movie, index) => (
          <Card key={index} item={movie} />
        ))}
      </section>
    </main>
  );
}

或者,您可以为MovieList组件的每个"实例"提供一个唯一的Reaction键,以便组件在路由更改时重新挂载.

function App() {
  return (
    <>
      <Header />
      <Routes>
        <Route path="/" element={<MovieList key="none" />} />
        <Route
          path="/movies/bottom"
          element={<MovieList key="bottom" sort="bottom" />}
        />
        <Route
          path="/movies/unpopular"
          element={<MovieList key="unpopular" sort="unpopular" />}
        />
        <Route
          path="/movies/upcoming"
          element={<MovieList key="upcoming" sort="upcoming" />}
        />
      </Routes>
    </>
  );
}

Typescript相关问答推荐

Typescript问题和缩减器状态不会在单击时添加用途.属性'状态和调度'不存在于userContextType类型上'|null'

脉轮ui打字脚本强制执行图标按钮的咏叹调标签-如何关闭

React组件数组及其props 的类型定义

Angular 17 -如何使用新的@if语法在对象中使用Deliverc值

如何根据另一个属性的布尔值来缩小函数属性的返回类型?

在动态对话框中使用STEP组件实现布线

如何创建一家Reduxstore ?

声明文件中的类型继承

我怎样才能正确地输入这个函数,使它在没有提供正确的参数时出错

与toast.error一起react 中的Async TUNK错误消息

为什么上下文类型在`fn|curred(Fn)`的联合中不起作用?

TypeScrip-根据一个参数值验证另一个参数值

在Google授权后由客户端接收令牌

无法缩小深度嵌套对象props 的范围

使用RXJS获取数据的3种不同REST API

带有';的类型脚本嵌套对象可选属性错误满足';

我如何键入它,以便具有字符串或数字构造函数的数组可以作为字符串或数字键入s或n

通过函数传递确切的类型,但验证额外的字段

为什么 Typescript 无法正确推断数组元素的类型?

根据索引将元组拆分为两个块