首页 > 解决方案 > React 路由器、redux、异步 API 请求和旧数据闪存

问题描述

假设我有以下代码(例如):

import React from 'react'

import { Route, Link, Switch } from 'react-router-dom'

import { useSelector, useDispatch } from 'react-redux'

import { useEffect } from 'react'

import { v4 as uuid } from 'uuid'

const Component1 = () => {
  const items = useSelector(state => state.app.items);

  const dispatch = useDispatch();

  useEffect(() => {
    const url = makeUrl();

    dispatch(fetchItems(url));
  }, []);

  return (
    <p>
      Component1 renders!
      <ul>
        {items.map(item => {
          return (
          <li key={uuild()}>
            <Item1 {...item} />
          </li>);
        })}
      </ul>
    </p>
  )
}

const Component2 = () => {
  const items = useSelector(state => state.app.items);

  useEffect(() => {
    const url = makeUrl();

    dispatch(fetchItems(url));
  }, []);

  return (
    <p>
      Component2 renders!
      <ul>
        {items.map(item => {
          return (
          <li key={uuild()}>
            <Item2 {...item} />
          </li>);
        })}
      </ul>
    </p>
  )
}

const MainComponent = () => {
  return (
    <>
      <Switch>
        <Redirect exact from="/" to="/component1"/>
        <Route exact path="/component1" component={Component1} />
        <Route exact path="/component2" component={Component2} />
      </Switch>
      <Link to="/component1">Component1</Link>
      <Link to="/component2">Component2</Link>
    </>
  )
}

有两条路由导航到两个不同的组件,每个组件都有自己独特的 UI/布局、API 请求逻辑等。当我移动到任一路由时,相应的组件就会呈现。

useEffect一切都按预期工作,但请注意,我在组件第一次使用特殊的第二个参数呈现后发出 API 请求。因此,当 url 更改时,旧组件卸载,另一个安装在他的位置,从而产生新的 API 请求。在每个组件内部,我都依赖于状态,即items属性。发送 API 请求并在fetchItems准备好时设置新数据,因此组件重新渲染。

问题是,在另一部分数据准备好之前,我的状态包含一些旧的,现在与上次请求无关的数据。当显示新组件时,它会渲染一次旧数据,然后才会发出新请求。这会导致新布局显示旧数据,这并不总是有意义的。

我可以通过在内部发出请求之前清除所有数据来缓解这个问题fetchItems。但是,由于反应效果的工作方式,它只会在 url 更改后发生,所以我的组件将使用旧数据呈现,然后才会使用空数据呈现。如果我的布局有点复杂,显示旧数据的新 UI 的闪烁会变得很明显。是否有一种很好且轻松的方式来处理它并使我的组件在功能组件内的新数据可用之前不会重新渲染旧数据?

我知道我可以为状态中的每种类型的数据创建两个单独的字段,但这根本不能解决问题,因为我的组件会从它自己的最后一个请求中呈现相应的数据。

标签: javascriptreactjsasynchronousreduxreact-router

解决方案


推荐阅读