#javascript #reactjs #react-router
#javascript #reactjs #react-router
Вопрос:
В настоящее время я передаю свое состояние при изменении маршрута, как показано ниже:
<Link to={{
pathname:`/transactions/${props.transaction.id}`,
state: {transaction: props.transaction}
}}> View Details </Link>
Моя логика заключается в том, что если существует «location.state.transaction», не извлекайте новые данные, иначе извлекайте данные.
Теперь недостаток заключается в перезагрузке страницы. Приложению необходимо получить новые данные, если пользователь перезагружает страницу. Я думал, что «location.state» будет очищен при перезагрузке, но, по-видимому, состояние сохраняется в sessionStorage.
Как мне обойти это? Я мог бы просто получать новые данные каждый раз, но они не должны извлекать данные при нажатии на ссылку «Просмотр сведений».
Ответ №1:
Если вы используете перехваты react, вы можете использовать window.history
их напрямую для очистки состояния без запуска повторного запроса. Это лучше, чем использовать метод useHistory
hook replace
, который приведет к повторному запуску вашего компонента.
window.history.replaceState({}, document.title)
Комментарии:
1. Это должен быть принятый ответ. Для этого требуется какая-либо сторонняя библиотека, и она также не перезагружает браузер. Большое спасибо @frodo2975
2. Спасибо за это! помогло мне с тостами, которые не сбрасывались при обновлении
Ответ №2:
Я также столкнулся с этой проблемой, и в итоге я получил историю браузера из react router и очистил определенные свойства location.state. Так что в вашем случае это было бы transaction
. Я сделал это componentDidMount
так, чтобы после первого перехода на страницу этого свойства больше не было,
import createHistory from 'history/createBrowserHistory'
...
componentDidMount(){
const history = createHistory();
if (history.location.state amp;amp; history.location.state.transaction) {
let state = { ...history.location.state };
delete state.transaction;
history.replace({ ...history.location, state });
}
}
Комментарии:
1. хорошее решение!!
2. отправляется @@router / LOCATION_CHANGE. но состояние остается прежним
Ответ №3:
Существует лучший подход без использования сторонней библиотеки.
Мы можем использовать history.replace()
https://github.com/ReactTraining/react-router/blob/master/packages/react-router/docs/api/history.md
componentDidMount(){
const {location,history} = this.props;
//use the state via location.state
//and replace the state via
history.replace()
}
Ответ №4:
В react Router V6 вы можете использовать useNavigate() для очистки состояния для текущего пути:
import React, { useEffect } from "react";
import { useLocation, useNavigate } from "react-router-dom";
useEffect(() => {
const location = useLocation();
const navigate = useNavigate();
navigate(location.pathname, {});
// reload and pass empty object to clear state
// we can also use replace option: ..., {replace: true}
}, []);
Комментарии:
1. Что, если вы отображаете вещи на основе location.state? например.
location.state.bananas === "bananas" ? "more bananas" : "no bananas for you"
всегда будет выдавать последнее, потомуuseEffect()
что перезагрузит все2. Это сработало для меня лучше, чем общепринятый ответ. У меня есть многоразовый компонент breadcrumb, который просто анализирует URL-адрес, но отображает crumbTitle, если он отправлен через state, и хотел сохранить его, но я также отправил строку, которая вызвала открытие модала. Я не хотел, чтобы модал повторно открывался при обновлении, но я хотел сохранить crumbTitle, иначе он отображал бы идентификатор из параметров url. Я смог обновить состояние так, как хотел, и сохранить crumbTitle с помощью этого решения. Я не уверен, почему принятый ответ не работает для этого сценария.
3. Я также только что узнал, что вы можете передать пустую строку вместо location . имя пути.
Ответ №5:
После того, как вы использовали состояние, снова отправьте действие с пустым состоянием, чтобы очистить состояние.
this.props.dispatch(replace({
...this.props.location,
state: undefined
});
Комментарии:
1. недооцененный ответ
Ответ №6:
history.replace({ state: {} })
. Если вы также хотите перенаправить пользователя куда-нибудь, используйте history.replace({ pathname: '/profile/me', state: {} })
Ответ №7:
Это то, что может сработать.
const history = useHistory();
// consume the history.location.state and reset the state
useEffect(() => {
history.replace(`/transactions/${history.location.state.transaction.id}`, {});
}, []);
Ответ №8:
Я бы посоветовал не использовать location
prop здесь, а создать маршрут (где бы вы его ни определяли) с помощью path: /transactions/:transactionId
, и перехватить transactionId
в prop props.match.params.transactionId
внутри целевого компонента. Затем componentDidMount
вы можете отправить действие запроса API для получения транзакции. Не забудьте удалить state
параметр из реквизита ссылки.
Ответ №9:
В React Router v6 вы можете сделать:
const location = useLocation();
const navigate = useNavigate();
const state = location.state;
// Do some stuff with the state
// ...
// Clear the state after
navigate(location.pathname, { replace: true });
Переход на текущую страницу не даст никакого видимого эффекта, кроме очистки состояния (изменения истории).
Ответ №10:
Ни один из них не сбросил бы мое состояние с помощью useNavigate. Что мне нужно было сделать, так это настроить useEffect для навигации.
...
const navigate = useNavigate()
...
useEffect(() => {
// set state here
....
},[navigate]