我在一个Reaction应用程序中使用了Reaction-Router-Domv6.我有带URL参数的路由.当参数更改时,路径的元素props (这是一个组件)会重新呈现,但在组件中的数据变得不一致之前,将参数作为依赖项的useEffect不会触发,从而导致应用程序崩溃(白屏).我的解决方案是用组件包装我所有的路由元素props ,该组件将参数作为关键字传递给我想要渲染的组件.它工作得很好,但我觉得我不应该这么做.要么是有更合适的解决方案,要么是我以后会遇到我没有预料到的问题.我很感激在这件事上的任何建议.谢谢

下面是我的包装器组件:

const PageWrapper = ({page}) => {
  const params = useParams();
  const key = JSON.stringify(params);
  return <div key={key}>{page}</div>
}

这就是我所有的路由:

<Route
    path={`thing_type/:thing_type_id`}
    element={
        <PageWrapper
            page={<ThingTypePage/>}
            />
    }
/>

让我的所有路由看起来像这样有点难看和混乱,但它都包含在我的路由文件中,所以我可以处理它.

我try 将参数作为键直接传递给元素属性,但它在Reaction-Router-DomV6中不受支持.

编辑: 只有当我两次导航到同一页面,但参数不同时,问题才会出现.如果在这两个页面之间导航到另一个页面,则不会出现问题.导致崩溃的数据不一致来自于Reaction应用程序中缓存的客户端数据与从服务器获取的数据的混合.这是My Page的缩写示例:

const ThingTypePage = () => {
    const {thing_type_id} = useParams();
    const {cachedStaticData} = React.useContext(Context);

    const [data, setData] = useState(null);
    useEffect(() => {
        setData(null);
        const body = {thing_type_id};
        const onSucceeded = (response) => setData(response.data);
        const onFailed = (err) => setData(false);
        myFetch("myBackendUrlExtension", body, onSucceeded, onFailed);
    }, [thing_type_id])

    if(data === null) return <div>Loading...</div>;
    if(data === false) return <div>Failed to load</div>;
    
    const things = data.instances;
    const thingTypeObjectStructure = getThingTypeObjectStructure(cachedStaticData, thing_type_id);
    // at this point things = data from previous fetch, when thing_type_id = old_id
    // but thingTypeObjectStructure has the updated value, using thing_type_id = new_id
    
    return (
        <div key={`ThingTypePage-${thing_type_id}`}>
            <ThingsTable
                // here 'things' is being rendered with a false assumption of their object structure
                // causing crashes (accessing undefined)
                things = {things}
                structure = {thingTypeObjectStructure}
                />
        </div>
    )

}

推荐答案

我想说,这有点反模式,如果您需要对大多数路由执行此操作,则您的路由组件中存在一些逻辑问题.我认为你根本没有必要这么做,真的.

这里看起来105 data 106 thingTypeObjectStructure依赖于thing_type_id路径参数值,并且当获取的data状态和计算/派生的thingTypeObjectStructure由于Reaction组件状态更新与渲染周期一起工作的方式而变得不同步时,这成为一个问题.

我的建议是将thingTypeObjectStructure也转换为React状态,这样它就可以被计算和更新102作为data状态.

示例:

const ThingTypePage = () => {
  const { thing_type_id } = useParams();
  const { cachedStaticData } = React.useContext(Context);

  const [data, setData] = useState(null);

  useEffect(() => {
    setData(null);

    const body = { thing_type_id };
    const onSucceeded = ({ data }) => {
      setData({
        things: data.instances,
        structure: getThingTypeObjectStructure(
          cachedStaticData,
          thing_type_id
        ),
      });
    };
    const onFailed = () => setData(false);

    myFetch("myBackendUrlExtension", body, onSucceeded, onFailed);
  }, [cachedStaticData , thing_type_id]);

  if (data === null) return <div>Loading...</div>;
  if (data === false) return <div>Failed to load</div>;
    
  const { things, structure } = data;
    
  return (
    <div>
      <ThingsTable
        things={things}
        structure={structure}
      />
    </div>
  );
}

现在您应该能够从发送的内容中删除包装器组件了.

<Route
  path="thing_type/:thing_type_id"
  element={<ThingTypePage />}
/>

Reactjs相关问答推荐

Shadck/ui Select -当用户 Select 项目时更改状态

react 下拉菜单任务

捕获表单数据时的Reactjs问题

React:关于useEffect钩子如何工作的困惑

页面永远加载API/从数据库获取数据

如何使用TouchStart/TouchEnd在Table ReactJS中交换位置?

更改点几何体的坐标会将其隐藏

shadcn输入+窗体+Zod;一个部件正在改变要被控制的不受控制的输入;

关于forwardRef,我可以';我不理解第二个用例

tRPC/react-query,在所有查询完成之前,组件不会收到任何 useQuery 的结果

如何在react 中过滤数组的数组?

REACT: UseState 没有更新变量(ant design 模态形式)

在 monorepo 内的工作区或库之间共享 redux 状态

ReactJS:在导航栏中使用 Select inside Link 组件时如何避免重定向?

Suspense/Await - 解析数据加载/保存到状态后无限循环

Next.js i18n 路由不适用于动态路由

如何在 ChartJS 中操作 Y 轴

如何在 React 中的 Material Ui 多选中设置默认值?

服务器端分页未按预期工作

在 React 中访问作为 prop 传递的状态变量