Использование CreateBrowserRouter из React Router с хранилищем Redux

Я пытаюсь реализовать как Redux, так и React-Router в проекте блога React, в котором я получаю данные из API и сохраняю их в Redux, однако они не отображаются и ошибок не возникает.

Я попробовал следующий код в своем App.jsx

const getRouter = (store) => {
  return (
    createBrowserRouter(
      createRoutesFromElements(
        <Route path = "/" element = {<Layout />}>
          <Route
            index
            element = {<PostList />}
            errorElement = {<Error />}
            loader = {(arg) => {
              arg.post = store.getState().posts
            }}
          />
          <Route  path='/posts' element = {<PostForm />}>
            <Route  />
          </Route>
          <Route path = "*" element = {<NotFound />} />
        </Route>
      )
    )
  )
}

export default function App() {
  <Provider store = {store}>
    <RouterProvider router = {getRouter(store)} />
  </Provider>
} 
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Улучшение производительности загрузки с помощью Google Tag Manager и атрибута Defer
Улучшение производительности загрузки с помощью Google Tag Manager и атрибута Defer
В настоящее время производительность загрузки веб-сайта имеет решающее значение не только для удобства пользователей, но и для ранжирования в...
Безумие обратных вызовов в javascript [JS]
Безумие обратных вызовов в javascript [JS]
Здравствуйте! Юный падаван 🚀. Присоединяйся ко мне, чтобы разобраться в одной из самых запутанных концепций, когда вы начинаете изучать мир...
Система управления парковками с использованием HTML, CSS и JavaScript
Система управления парковками с использованием HTML, CSS и JavaScript
Веб-сайт по управлению парковками был создан с использованием HTML, CSS и JavaScript. Это простой сайт, ничего вычурного. Основная цель -...
JavaScript Вопросы с множественным выбором и ответы
JavaScript Вопросы с множественным выбором и ответы
Если вы ищете платформу, которая предоставляет вам бесплатный тест JavaScript MCQ (Multiple Choice Questions With Answers) для оценки ваших знаний,...
1
0
291
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

Функция загрузчика маршрута принимает один объект аргумента со свойствами params и request. arg.post не определено.

Компонент App также должен вернуть JSX, который он собирается отобразить.

Если вам нужно получить доступ к контексту хранилища Redux в загрузчике маршрутов, я бы предложил просто импортировать store и получить доступ непосредственно в функции загрузчика вместо закрытия экземпляра хранилища в маршрутизаторе. Проблема с имеющимся у вас кодом заключается в том, что он будет создавать новый маршрутизатор каждый раз, когда обновляется магазин и выполняется повторная отрисовка компонента Provider.

Пример:

const router = createBrowserRouter(
  createRoutesFromElements(
    <Route element = {<Layout />}>
      <Route
        path = "/"
        element = {<PostList />}
        errorElement = {<Error />}
        loader = {({ params, request }) => {
          const { posts } = store.getState();
          // return some value to `PostList` component
        }}
      />
      <Route path='/posts' element = {<PostForm />}>
        ...
      </Route>
      <Route path = "*" element = {<NotFound />} />
    </Route>
  )
)

export default function App() {
  return (
    <Provider store = {store}>
      <RouterProvider router = {router} />
    </Provider>
  );
}

Если вы действительно хотите по-прежнему использовать функцию для получения маршрутизатора, то хотя бы запомните маршрутизатор, чтобы он предоставлялся как стабильная ссылка и не создавался заново каждый раз при App или Provider повторном рендеринге.

export default function App() {
  const router = React.useMemo(() => getRouter(store), [store]);

  return (
    <Provider store = {store}>    
      <RouterProvider router = {router} />
    </Provider>
  );
}

Если вам не нужно использовать загрузчик маршрутов, кроме как для доступа и возврата значения хранилища, есть лучшие альтернативы. Вы можете просто использовать хуки useDispatch и useSelector, экспортированные из react-redux, в компонентах, которым необходимо подписаться на обновления состояния.

Пример:

...
import { useSelector } from 'react-redux';
...

const PostList = () => {
  const posts = useSelector(state => state.posts);

  ...

};
const router = createBrowserRouter(
  createRoutesFromElements(
    <Route element = {<Layout />}>
      <Route
        path = "/"
        element = {<PostList />}
        errorElement = {<Error />}
      />
      <Route path='/posts' element = {<PostForm />}>
        ...
      </Route>
      <Route path = "*" element = {<NotFound />} />
    </Route>
  )
)

export default function App() {
  return (
    <Provider store = {store}>
      <RouterProvider router = {router} />
    </Provider>
  );
}

Основное преимущество использования перехватчика useSelector заключается в том, что это подписка: при обновлении выбранного состояния подписанные компоненты будут запускаться для повторной визуализации с текущим значением состояния. Это не тот случай, когда используется store.getState, он получает текущее значение только один раз, в момент вызова getState, и не подписывается на будущие изменения.

есть ли другой способ получить доступ к хранилищу без функции загрузчика? и какой еще способ получить доступ к роутеру без использования функции

user20984108 14.04.2024 01:55

@ user20984108 Если вам вообще не нужна функция загрузчика, просто используйте хуки useDispatch и useSelector в своих компонентах, чтобы получить доступ к функции dispatch и выбрать состояние из хранилища. Вам не нужно использовать функцию для создания объекта router, см. мой первый пример. Если внешних зависимостей нет, просто объявите router вне ReactTree, чтобы это была стабильная ссылка (например, созданная один раз и являющаяся одной и той же ссылкой на протяжении всего существования экземпляра приложения). Имеет ли все это смысл? Вам нужно рассматривать это как примеры?

Drew Reese 14.04.2024 02:38

Было бы более полезно, если бы я мог видеть их в качестве примера.

user20984108 15.04.2024 01:15

Другие вопросы по теме