#javascript #reactjs #react-router-dom
Вопрос:
Это часто возникает, но, похоже, ни одно решение не работает, и я чувствую, что исчерпал все возможные варианты, поэтому я обращаюсь сюда, полагая, что это может быть немного другой сценарий, а не дубликат. Если есть существующее решение, которое работает, я буду рад, если мне покажут обратное.
В моем последнем проекте create-react-app у меня не было проблем с отображением новых страниц с маршрутизатором и историей использования. Используя точно такую же настройку, я столкнулся с проблемой, когда history.push(url)
изменяется URL-адрес в адресной строке, но страница не отображается повторно.
Я использую:
- Реагировать v17.0.2
- реагировать-маршрутизатор-dom v5.3.0
- история v5.0.1 (также предпринята попытка на v4.10.1)
App.js
import React from 'react';
import { BrowserRouter as Router, Route, Switch } from "react-router-dom";
import { Page } from './stories/Page';
import './App.css';
function App() {
return (
<Router>
<Switch>
<Route exact path="/">
<Page homepage={true} />
</Route>
<Route path="/project/([a-zA-Z0-9] )/([a-z-0-9] )/([a-z-0-9] )/" render={urlprops =>
<Page projectID={urlprops.match.params[0]} homepage={false} />
} />
<Route path="/project/([a-zA-Z0-9] )/([a-z-0-9] )/" render={urlprops =>
<Page projectID={urlprops.match.params[0]} homepage={false} />
} />
</Switch>
</Router>
);
}
export default App;
component-page.js
import React, { useEffect, useState, useCallback } from 'react';
import PropTypes from 'prop-types';
import { useHistory } from 'react-router-dom';
import './menuitem.css';
export const Component = ({ url, ...props }) => {
let history = useHistory();
function handleItemClick(e) {
history.push(url); // <- calls fine, tested with logging to console
}
...
Я видел, как старые решения предлагали передавать реквизиты истории через маршрутизатор, но в моем последнем приложении я смог использовать настройку выше, и любой вложенный подкомпонент уровня мог бы вызвать крючок истории использования и использовать push, если бы они были настроены так component-page.js выше. Поэтому я не показал компоненты между App.js и component-page.js исходя из убеждения, что это не должно иметь отношения к useHistory
правильному функционированию.
Possibly relevant:
- If I enter the URLS in the address bar and hit return, Router renders the correct components, suggesting Router and Switch work fine with a freshly loaded page.
- I have React dev tools set up to blink on
components when they re-render. Afterhistory.push(url)
is called all
components blink, though none re-render (visually, at least). - Downgrading history to 4.10.1 seemed to fix a lot
of the recent reports of this issue for others. I had no such luck. Apparently there was/is a bug with react-router-dom v5 which meant history.push was not working with history v5 . - Я также поместил простой компонент кнопки в компонент страницы, который отправил запрос на history.push(«url-адрес строки здесь») с той же проблемой. Он звонит, адресная строка меняется, страница не отображается повторно. На мой взгляд, это исключает, что это какая-то проблема с гнездованием, в которую я все равно не верил.
Обновить
Проверка истории в консоли после вызова history.push('url string')
показывает следующее в свойстве location. Похоже, что он действует так, как задумано (я ожидаю, что имя пути будет соответствовать URL-адресу, на который я пытался указать).
{
"pathname": "url string",
"search": "",
"hash": "",
"key": "ctks7v"
}
Обновление 2
Возможный прогресс. В моем компоненте страницы я вызываю fetch в крючке, чтобы поймать любое обновление, например так:
useEffect(() => {
apiFetchProject(projectID);
}, []);
Теперь я задаюсь вопросом, не моя ли это проблема? Что этот крючок не рассматривает URL-адрес как изменение, требующее запуска apiFetchProject(projectID)
. Причина, по которой я говорю это, заключается в том, что вызовы консоли подтверждают, что этот крючок не вызывается здесь после моей истории.push, но происходит консольный вызов компонента Страницы. Я пытался вызвать крючок с любым изменением, props.location
но каждый раз это возвращается как неопределенное, что означает, что крючок не вызывается.
Обновление 3
Если на странице я использую import { useLocation } from "react-router-dom";
с let location = useLocation();
и позволяю крючку искать изменения location
, страница теперь успешно звонит fetch
после history.push
звонка. Но что-то кажется неправильным в том, чтобы делать и это тоже? Я чувствую, что воспринял бы это как стандартную инструкцию.
Мне нужно добавить его в каждый компонент, чтобы увидеть повторную визуализацию чего-либо. Страница «Выборка» хранится как состояние и передается в качестве поддержки подкомпонентам. Изменение этого состояния должно автоматически повторно отображать все переданные ему подкомпоненты, как это происходит при загрузке страницы.
Комментарии:
1. Некоторое время назад у меня была аналогичная проблема, и я думаю, что решил ее, «обманув» react в повторном рендеринге, предоставив ему новый ключ с использованием метки времени.
Ответ №1:
вместо URL-адреса укажите путь (‘/home’)
Комментарии:
1. Я не уверен, что понимаю это предложение? URL — адрес должен быть динамической переменной и в любом случае должен соответствовать одному из путей переключения. С точки зрения отладки, я попытался использовать строки вместо переменной url, чтобы исключить эту проблему (ее не было).
2. Извините, но это вообще не отвечает на вопрос — вопрос по сути сводится к «У меня проблема с отображением новых страниц с маршрутизатором и историей использования при вызове history.push(url). URL-адрес в адресной строке изменяется, но страница не отображается повторно».