Как мне очистить location.state в react-router при перезагрузке страницы?

#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]