Содержимое не изменяется, когда в браузере выполняется перемотка назад / вперед с данными о состоянии в React + Redux - PullRequest
4 голосов
/ 13 апреля 2019

Я хочу вытащить subreddits и показать пользователю в виде списка. Когда пользователь меняет subreddit из меню параметров, я помещаю состояние в историю браузера.

Демонстрационная версия : https://react -7qfrxx.stackblitz.io

Размножение:

  1. Открыть ссылку выше
  2. Выберите frontend из списка. В списке выберите reactjs снова.
  3. Вы увидите изменения URL (добавляется subreddit)
  4. Теперь нажмите кнопку браузера назад и вперед.
  5. Вы увидите, что URL-адрес изменяется , но содержимое такое же .

Живой редактор : https://stackblitz.com/edit/react-7qfrxx

In AsyncApp.js Line 36:

this.props.dispatch(push('/' + nextSubreddit))

Как я могу показать предыдущее или следующее кэшированное / состояние пользователю при нажатии назад / вперед? Может ли кто-нибудь отредактировать мое онлайн-приложение, чтобы показать мне правильный путь? Я пытаюсь решить эту проблему с 2 дня и не повезло.


enter image description here

Мне нужно сделать это без обновления страницы. (Асинхронный)

Ответы [ 4 ]

2 голосов
/ 14 апреля 2019

Предыдущее решение не сработало, поэтому вот мой обновленный ответ: я думаю, что вам лучше всего послушать тип действия LOCATION_CHANGE connected-react-router и отправить Вы выбираете Subreddit там. Использование LOCATION_CHANGE недокументировано в проекте connected-react-router, однако docs старого проекта response-router-redux делает упомяните об этом.

На самом деле мы можем создать функцию промежуточного программного обеспечения для этого:

import { LOCATION_CHANGE } from 'connected-react-router'
import { selectSubreddit } from './actions';

export const listenRouteMiddleware = ({ dispatch, getState }) => (next) => (action) => {
  if (action.type === LOCATION_CHANGE) {
    const { pathname } = action.payload.location;
    if (pathname !== '/') {
      const pathArray = pathname.split('/');
      const selectSub = pathArray[pathArray.length - 1];
      next(action); // before dispatch, otherwise history breaks
      dispatch(selectSubreddit(selectSub));
      return;
    }
  }
  next(action);
}

Затем добавьте его в другое промежуточное ПО:

import thunkMiddleware from 'redux-thunk'

import { createBrowserHistory } from 'history'
import { applyMiddleware, compose, createStore } from 'redux'
import { routerMiddleware } from 'connected-react-router'
import createRootReducer from './reducers'
import { listenRouteMiddleware } from './middleware';
export const history = createBrowserHistory()

export default function configureStore(preloadedState) {
  const store = createStore(
    createRootReducer(history), // root reducer with router state
    preloadedState,
    compose(
      applyMiddleware(
        listenRouteMiddleware,
        routerMiddleware(history), // for dispatching history actions
        thunkMiddleware
        // ... other middlewares ...
      ),
    ),
  )

  return store
}

Измените обработчик изменений, чтобы выдвигать новый URL только после выбора параметра:

handleChange(nextSubreddit) {
  this.props.dispatch(push('/' + nextSubreddit))
}

Вот и все! Чтобы увидеть рабочий пример, проверьте: Редактор , Приложение

1 голос
/ 14 апреля 2019

Проблема с вашим текущим решением заключается в том, что вы храните значение состояния selectedSubreddit в двух местах - Redux и url.Такого рода дублирования состояний обычно следует избегать.Вы используете connected-react-router lib, поэтому у вас пока не возникает слишком много проблем, но в более крупном приложении с такими вещами может быть довольно сложно справиться.

Также в вашем приложении есть два маршрута, /frontend и /reactjs, но вы не определяете какие-либо <Route/> компоненты.

Я думаю, что ваша структура компонентов должна выглядеть примерно так,

<Router>
  <>
    <Route exact path="/frontend" component={SubReddit}/>
    <Route exact path="/reactjs" component={SubReddit}/>
  </>
</Router>

А затем в componentDidMount из <SubReddit/> вы просто проверяете опору location, которую маршрутизатор предоставляет для выбранного в данный момент субредита.Переход на другой subreddit - это просто вопрос навигации (для этого используйте компонент реакции-маршрутизатор <Link/>).Таким образом, URL становится источником правды для выбранного в настоящее время subreddit.

Redux полностью излишен для простого управления списком сообщений subreddit, но достаточно справедлив, если это упражнение использовать его для практики.

1 голос
/ 14 апреля 2019

Вам нужно получить данные на основе маршрута, а не состояния.Выбирая выпадающий список, меняйте только маршрут.Вы можете использовать connected-react-router для прослушивания изменения URL.Когда маршрут изменен, он будет извлекать данные на основе маршрута.

function mapStateToProps(state) {
  var { selectedSubreddit, postsBySubreddit } = state;

  // Listen to the connected-react-router API for URL change.
  selectedSubreddit = state.router.location.pathname === "/" ? "reactjs" : state.router.location.pathname.split("/")[1];

  const { isFetching, lastUpdated, items: posts } = postsBySubreddit[
    selectedSubreddit
  ] || {
    isFetching: true,
    items: []
  }

  return {
    selectedSubreddit,
    posts,
    isFetching,
    lastUpdated
  }
}

Вот ответвление.https://stackblitz.com/edit/react-wxfdea

Вот исправленное приложение.https://react -wxfdea.stackblitz.io

URL обновлены.

0 голосов
/ 14 апреля 2019

Причина, по которой это не работает для вас, заключается в том, что вы читаете только имя subreddit из состояния Redux, а не смотрите URL. Вы можете получить URL-адрес из состояния, посмотрев на местоположение в маршрутизаторе.

Таким образом, простое исправление состоит в том, чтобы вместо сохранения и чтения selectedSubreddit как отдельной части избыточного состояния всегда вычислять его на основе URL-адреса. Измените mapStateToProps в AsyncApp.js следующим образом:

  const { router, postsBySubreddit } = state;
  const selectedSubreddit = router.location.pathname.substr(1) || 'reactjs';
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...