props.location 未定义路由组件

props.location is undefined with route component

我正在尝试 运行 代码片段如下:

class App extends Component {
  render() {
    return (
      <Router>
        <div className="App">
          <Navbar></Navbar>
          <Routes>
            <Route path="/" element={<Home></Home>} />
            <Route path="/about" element={<About></About>} />
            <Route path="/contact" element={<Contact></Contact>} />
            <Route path="/challenges/*" element={<Challenges></Challenges>} />
            <Route path="*" element={<NotFound />} />
          </Routes>
        </div>
      </Router>
    );
  }
}
let a = 0;

const Challenges = (props) => {
  console.log(++a);
  console.log(window.location.pathname);
  const path = props.location.pathname;
  const slug = path.split("/").slice(path.split("/").length - 1)[0];
  const challenge = challenges.find((challenge) => challenge.slug === slug);
  return (
    <div>
      <h1>30 Days Of React Challenge</h1>
      <ul>
        {challenges.map(({ name, slug }) => (
          <li key={name}>
            <NavLink to={`/challenges/${slug}`}>{name}</NavLink>
          </li>
        ))}
      </ul>
      <Routes>
        <Route
          exact
          path="/challenges"
          element={<h1>Choose any of the challenges</h1>}
        />

        <Route path={path} element={<Challenge challenge={challenge} />} />
      </Routes>
    </div>
  );
};

我想获取 Challenges 路线组件的路径,但它抛出错误: 无法读取未定义的属性(读取 'pathname') 我尝试记录变量“a”和“window.location”进行测试,它记录了两次,如下所示:

1
/challenges
2
/challenges

我的问题是为什么我不能获取 props.location.pathname 的值,为什么它两次 运行 并且第二次它抛出错误为什么不在第一次。 谢谢你帮助我!希望你今天过得愉快。

问题

  1. react-router-dom v6 Route 通过 element 属性呈现的组件不接收 route props.
  2. 路由子组件必须使用反应钩子来访问路由上下文,即useParamsuseLocation , useNavigate, 等等...因此必须是函数组件。
  3. console.log 调用在函数体中,因此这些是无意的 side-effects。这可能就是它们被调用两次的原因,假设应用程序被渲染到 React.StrictMode 组件中。

解决方案

Challenges 应该使用 uselocation 挂钩来访问路径名。将控制台日志移动到 useEffect 挂钩中,以便在每次渲染时调用一次 到 DOM.

const Challenges = (props) => {
  const { pathname } = useLocation();

  useEffect(() => {
    console.log(++a);
    console.log(pathname);
  });

  const path = pathname;
  const slug = path.split("/").slice(path.split("/").length - 1)[0];
  const challenge = challenges.find((challenge) => challenge.slug === slug);

  return (
    <div>
      <h1>30 Days Of React Challenge</h1>
      <ul>
        {challenges.map(({ name, slug }) => (
          <li key={name}>
            <NavLink to={`/challenges/${slug}`}>{name}</NavLink>
          </li>
        ))}
      </ul>
      <Routes>
        <Route
          path="/challenges"
          element={<h1>Choose any of the challenges</h1>}
        />

        <Route path={path} element={<Challenge challenge={challenge} />} />
      </Routes>
    </div>
  );
};

v6 api-reference