[英]Defer state update / rerender in React
我创建了一个 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 state 臃肿。这可能是个问题还是我想象的?我可以分析一下吗?)
这让我想到了我的问题:React 中是否有一种方法可以以某种方式推迟完整的重新渲染并在新的 state 生效之前保留旧的 state 一段时间?
好吧,假设您使用的是 Apollo Client,您正在寻找的是previousData
钩子结果属性
https://www.apollographql.com/docs/react/data/queries/#previousdata
根据文档
一个 object 包含最近一次执行此查询的结果。
如果这是查询的第一次执行,则此值未定义。
所以类似的东西(通过将image
变量与?.
(可选链接)你可以避免 boolean 变量来决定是否显示图像)
const { data, loading, error, previousData } = useQuery(/* ... */);
const image = data?.image?.base64 || previousData?.image?.base64;
注意:我建议您更改加载逻辑以仅在加载且未设置image
时显示加载微调器,以避免加载微调器和上一个图像一起显示。 如果出现错误,您最终可以隐藏图像。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.