我正在从我的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)
最终执行后第二次重新渲染我了解我的方法存在的问题。但是我看不到另一种方式。 必须使用钩子。
有什么想法吗?
答案 0 :(得分:1)
一种快速的解决方法是在列表中添加一个关键道具:
<List key={page} page={page} />
当页面值更改时,将卸载“列表”组件,并呈现一个新组件。新的渲染器中将没有任何以前的数据,因此您将只获得2个渲染器,而不是3个。
这意味着您不必再将先前的数据设置为null
。
如果执行此操作,则需要在调用useEffect
之前检查组件是否仍安装在setItems
中,否则,您将尝试在未安装的组件上设置状态。您可以编写:
if(setItems) {
setItems(data)
}
但是更改关键道具有点麻烦,所以我将研究其他方法来解决您的问题。
也许您应该将数据传递到列表中,而不是由列表负责获取数据,并且页面状态和数据都在父组件中?
尽管如此,使用页面更改密钥应该可以。
答案 1 :(得分:0)
use this method :
useEffect(() => {
fetch(`http://some_url_to_fetch_items.com?PAGE=${props.page}`)
.then((data) => {
setItems(data);
})
}, []);
return (
<ul>
{items? items.map(item => (
<li key={item.id}>{item}</li>
)):"Data is Loading..."}
</ul>
)