【问题标题】:Defer state update / rerender in React在 React 中延迟状态更新/重新渲染
【发布时间】:2023-01-14 00:33:50
【问题描述】:

我创建了一个 React 组件,它向后端发送 GraphQL 查询以检索图像作为 base64 编码的字符串并在加载时显示它。在那之前,它会显示一个小的加载微调器。代码看起来或多或少像这样并且按预期工作:

const { data, loading, error } = useQuery(...)
const showImage = !loading && !error && data?.image?.base64
const showError = !loading && (error || !showImage)

return (
    <div>
        {loading && <img src={`/loading.gif`} />}
        {showError && <img src={`/error.png`} />}
        {showImage && <img src={`data:image/jpg;base64, ${data.image.base64}`}/>}
    </div>
)

但最重要的是,该控件还允许一些基本的图像操作(例如,将图像染成紫色的按钮),这是我用useState 实现的。本质上:

const [ purple, setPurple ] = useState(false)

const { data, loading, error } = useQuery(/* pass `purple` to backend */)
const showImage = !loading && !error && data?.image?.base64
const showError = !loading && (error || !showImage)

return (
    <div>
        {loading && <img src={`/loading.gif`} />}
        {showError && <img src={`/error.png`} />}
        {showImage && <img src={`data:image/jpg;base64, ${data.image.base64}`}/>}
        <input type={`checkbox`} onChange={_ => setPurple(!purple)} />
    </div>
)

所有这些也都很好,除了单击复选框后,旧图像就会消失,我会得到loading.gif,直到获取新图像。这并不出人意料,但却是不受欢迎的。我宁愿保留旧图像并在新图像到达后设置它。

我尝试将旧图像的 base64 字符串写入 useState 钩子并从那里读取它,直到它被新图像替换。那行得通,但我的印象是表现不佳。 (网站上有很多很多这样的组件,当用户滚动足够长的时间时,可能会加载数百个组件,这会导致 React 状态膨胀。这会是一个问题还是我想象的那样?我可以对此进行分析吗?)

这让我想到了我的问题:在 React 中有没有办法以某种方式推迟完全重新渲染并在新状态生效之前保持旧状态一段时间?

【问题讨论】:

    标签: javascript reactjs react-hooks


    【解决方案1】:

    那么,假设您使用的是 Apollo Client,您正在寻找的是 previousData 钩子结果属性

    https://www.apollographql.com/docs/react/data/queries/#previousdata

    根据文档

    包含最近的上一个结果的对象 这个查询的执行。

    如果这是查询的第一次执行,则此值未定义。

    所以类似的东西(通过将image变量与?.(可选链接)一起使用,您可以避免使用布尔变量来决定是否显示图像)

    const { data, loading, error, previousData } = useQuery(/* ... */);
    const image = data?.image?.base64 || previousData?.image?.base64;
    

    注意:我建议您更改加载逻辑以仅在加载时显示加载微调器并且未设置image,以避免加载微调器和上一个图像一起显示。如果出现错误,您最终可以隐藏图像。

    【讨论】:

      猜你喜欢
      • 2016-11-04
      • 2020-10-24
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-06-11
      相关资源
      最近更新 更多