React加载组件为什么在数据加载完成还是不消失?
我在用React写一个数据请求组件,加载动画在请求开始时显示了,但请求成功后却一直不消失,明明状态已经变成false了。这是怎么回事啊?
代码是这样写的,请求开始时我把isLoading设为true,成功后设为false。但实际运行时,加载图标一直卡着:
function ProductList() {
const [products, setProducts] = useState([]);
const [isLoading, setIsLoading] = useState(false);
useEffect(() => {
setIsLoading(true);
fetch('/api/products')
.then(res => res.json())
.then(data => {
setProducts(data);
setIsLoading(false); // 这里确实执行了
})
.catch(err => {
console.error(err);
setIsLoading(false);
});
}, []);
return (
{isLoading && } {/* 这个始终显示 */}
{products.map(p => (
- {p.name}
))}
);
}
我加了console.log确认过,请求成功时isLoading确实变成了false,但页面上的加载图标就是不消失,这是为什么?
setIsLoading(true)和fetch写在一起,可能导致加载状态没及时刷新。改成这样:如果还不行,可能是其他地方影响了渲染,检查下父组件或样式。
isLoading确实变成了false,但由于 React 的状态更新是异步的,再加上你可能没注意到的一个细节:fetch请求本身并不会自动终止组件的渲染流程。简单说,加载动画不消失的原因可能是状态更新和 DOM 更新不同步导致的。这里有一个更好的写法,不仅可以解决你的问题,还能让代码更优雅:
首先,确保你的
useEffect返回一个清理函数(cleanup function),这样如果组件卸载了,可以避免不必要的状态更新。改动点总结:
1. 加了一个
isMounted标识,防止组件卸载后还更新状态。2. 在
setIsLoading(false)前加了isMounted检查,确保不会对已卸载的组件进行无意义的状态更新。3. 调整了返回值部分的结构,避免潜在的渲染问题。
这个版本不仅解决了你的问题,还让你的代码更健壮、更清晰。React 里这种异步请求的场景其实挺常见的,记得养成好习惯,每次都要考虑组件的生命周期!