я пытаюсь запустить фрагмент кода, как показано ниже:
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.info(++a);
console.info(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, но он выдает ошибку: Не удается прочитать свойства неопределенного (чтение «имя пути») я пытаюсь зарегистрировать переменную «a» и «window.location» для проверки, и она регистрируется два раза следующим образом:
1
/challenges
2
/challenges
Мой вопрос в том, почему я не могу принять значение props.location.pathname и почему он запускается два раза, а во второй раз выдает ошибку, почему не в первый раз. Спасибо за помощь! Надеюсь, у тебя хороший день.
Route
, отображаемые с помощью element
prop, не получают реквизит маршрута.useParams
, useLocation
, useNavigate
и т. д., и поэтому должны быть функциональными компонентами.console.info
находятся в теле функции, так что это непреднамеренные побочные эффекты. Вероятно, поэтому они вызываются дважды, предполагая, что приложение визуализируется в компонент React.StrictMode
.Challenges
следует использовать хук uselocation
для доступа к имени пути. Переместите журналы консоли в хук useEffect
, чтобы они вызывались один раз за рендеринг в ДОМ.
const Challenges = (props) => {
const { pathname } = useLocation();
useEffect(() => {
console.info(++a);
console.info(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>
);
};
Компоненты перерисовываются по разным причинам: их свойства, контекст или состояние изменились, или их родитель(и) перерендерились. Если вы оберните свой компонент
Challenges
с помощьюReact.memo
, вы можете предотвратить его повторный рендеринг, если его свойства или состояние не изменятся, но вам часто не нужно беспокоиться об этом. Я также ожидал бы, чтоchallenges.find
потерпит неудачу, поскольку вы нигде не определилиchallenges
(по крайней мере, в показанном коде)