redux React Router(v6)无法在重新加载或手动键入路由时加载编程路由

p3rjfoxz  于 2022-11-12  发布在  React
关注(0)|答案(1)|浏览(159)

我正在尝试使用以下方法对项目进行编程路由:react - redux(普通redux)-react路由器v6-打字脚本也使用Vite而不是CRA(如果这有帮助)
贝娄是我的代码的简单版本:
App.tsx

<BrowserRouter>
<Routes>
<Route element={<Layout />}>
  <Route path="/" element={<itemsList />} />
  <Route path="/item">
    <Route path="/item/:itemId" element={<itemComponent />} />
  </Route>
  <Route path="*" element={<NotFound />} />
</Route>
</Routes>   
</BrowserRouter>

物料组件

const { itemId } = useParams();

const items = items.find((item) => {
    return item.id === itemId;
  });

  if (!item) {
    return <>{'Sorry!!!, Item Not Found'}</>;
  }

/* and the code for this certain (itemId) */

一切似乎都工作正常,我可以导航到/item/:itemId路线没有问题,但问题来了:如果我试图刷新页面,我得到的{'Sorry!!!, Item Not Found'},我把那里,如果没有项目也,如果我试图去到itemId页面手动我得到同样的错误
我搜索并找到了一些解决方案,但没有工作,大多数都过时了,我感谢帮助,让我知道如果你需要任何更多的信息

**编辑:**添加更多信息和代码,items是我使用redux-thunk从假json-server中获取的数据(我在ItemsList组件中获取它,但经过研究后,我使用以下代码直接从存储中获取它,这是我执行列表获取的唯一位置)

import { store } from './store';
import App from './App';
import { fetchItems } from './action-creators';
import { ItemsActions, ItemsState } from './types/';
import { ThunkDispatch } from 'redux-thunk';

(store.dispatch as ThunkDispatch<ItemsState, unknown, ItemsActions>)(
  fetchItems()
);

const root = ReactDOM.createRoot(
  document.getElementById('root') as HTMLElement
);
root.render(
  <React.StrictMode>
    <Provider store={store}>
      <BrowserRouter>
        <App />
      </BrowserRouter>
    </Provider>
  </React.StrictMode>
);

itemsList示例

{
  "items": [
    {
      "userId": "1",
      "id": "1",
      "title": "item Title",
      "body": "item body"
    },
   {
      "userId": "1",
      "id": "2",
      "title": "item Title2",
      "body": "item body2"
    }
}

fetchItems操作代码:

export const fetchItems = () => {
  return async (dispatch: Dispatch<ItemsActions>) => {
    dispatch({
      type: 'FETCH_ITEMS',
    });

    try {
      const {data} = await axios.get(basefetchItemsURL);

      dispatch({
        type: 'FETCH_ITEMS_SUCCESS',
        payload: data,
      });
    } catch (err) {
      if (err instanceof Error) {
        dispatch({
          type: 'FETCH_ITEMS_ERROR',
          payload: err.message,
        });
      }
    }
  };
};

有了上面的设置,我可以例如去路由(“/”或“/item”),它工作正常,itemsList is fetched normally Also i can go to (path="/item/:itemId") from the ItemsList component But once im on this page (path="/item/:itemId") example: (http://localhost:3000/item/1) and i refresh the page it get lost and i get error (tsx:33 Uncaught ReferenceError: item is not defined) and the itemsList also lost and i get empty array []'

eqzww0vc

eqzww0vc1#

item对象为undefined/falsey时,ItemComponent组件似乎可以正确处理“sad路径”,因为items是空数组,或者因为通过 predicate 函数的条件未找到匹配元素。
我认为问题是当应用程序被挂载时,作为React组件生命周期的一部分,fetchItems操作没有被调度。这确保了react-reduxProvider组件被挂载,并且有一个store对象提供给应用程序。
挂载App组件时,尝试从其中的useEffect挂接调度fetchItems
示例:

import { useEffect } from 'react';
import { useDispatch } from 'react-redux';

const App = () => {
  const dispatch = useDispatch();

  useEffect(() => {
    dispatch(fetchItems()); // <-- dispatch when App mounts
  }, []);

  return (
    <BrowserRouter>
      <Routes>
        <Route element={<Layout />}>
          <Route path="/" element={<ItemsList />} />
          <Route path="/item/:itemId" element={<ItemComponent />} />
          <Route path="*" element={<NotFound />} />
        </Route>
      </Routes>   
    </BrowserRouter>
  );
};

类似地,我怀疑您可能直接在路由组件文件中访问存储区。您还应该在React组件生命周期内从Redux存储区中选择items数组。在这里,您可以使用useSelector挂钩来选择适当的状态切片。
物料组件

import { useSelector } from 'react-redux';

const ItemComponent = () => {
  const items = useSelector(state => state.items); // *

  const { itemId } = useParams();

  const items = items.find((item) => item.id === itemId);

  if (!item) {
    return <>Sorry!!!, Item Not Found</>;
  }

  ...
};

****注意:*此处选择state.items假设这是您配置商店的方式,并且有一个名为items的组合缩减器。您需要从缩减器路径中选择项目状态,以确定组合状态树的结构。

相关问题