reactjs - ReactJS:在再次获取之前清空组件的旧获取数据
问题描述
我正在从我的 React 组件中获取远程数据。当数据准备好时,子组件就会被渲染。在加载数据时,会显示“数据正在加载……”文本。
当组件因props
更改而第二次渲染时,我将之前的数据设置为null
,以显示正在加载新数据。
const List = (props) => {
const [items, setItems] = useState(null);
useEffect(() => {
setItems(null);
fetch(`http://some_url_to_fetch_items.com?PAGE=${props.page}`)
.then((data) => {
setItems(data);
})
}, [props.page]);
if (!items) {
return "Data is loading ......."
}
return (
<ul>
{items.map(item => (
<li>{item}</li>
))}
</ul>
)
}
这种方法的问题是,当第二次渲染组件时,setItems(null);
代码并没有立即执行(可能是因为useEffect
异步执行)并且组件重新渲染了 3 次,而不是预期的 2 次:
- 由于道具更改,第一次重新渲染(但是使用旧数据,因为
setItems(null)
执行得太晚了) setItems(null)
最终执行后的第二次重新渲染- 获取数据后第 3 次重新渲染
我明白我的方法有什么问题。但我没有看到其他方法。必须使用钩子。
有任何想法吗?
解决方案
一个快速的解决方法是在您的列表中添加一个关键道具:
<List key={page} page={page} />
当 page 的值发生变化时,List 组件将被卸载,并呈现一个新的组件。新的将没有任何以前的数据,因此您只会获得 2 个渲染而不是 3 个。
这意味着您不必再设置以前的数据null
。
如果您这样做,您需要useEffect
在调用之前检查该组件是否仍然安装在您的组件中setItems
,否则您将尝试在未安装的组件上设置状态。你可以写:
if(setItems) {
setItems(data)
}
不过,更改密钥道具有点麻烦,所以我会研究其他方法来解决您的问题。
也许您应该将数据传递到列表中,而不是列表负责获取数据,并且将页面状态和数据都包含在父组件中?
不过现在,使用页面更改密钥应该可以工作。
推荐阅读
- java - 更改 Java Eclipse 代码中的输出颜色
- sql-server - '<' 和 '>' 等比较运算符如何处理字符串值?
- r - 在 R 中展开/估算时间序列
- vue.js - 将数据传递给 vue.js 方法
- seo - 在 AEM 中,我想添加
标签内的标签。架构内的多字段选项 - php - PHP MySQL - 为什么存储过程调用在 PHP 代码中意外结束
- list - python重新排序列表元素并转换为set
- matlab - 如何从日期时间中提取特定的时间范围?
- c++ - 如何让 UDP 套接字丢弃最早排队的数据包而不是新的传入数据包?
- javascript - React Native 如何调用 api 或无限期运行函数