React中useEffect内更新状态后如何正确触发组件重渲染?
你代码存在两个核心问题,对应解决方案如下:
核心问题1:useEffect用法错误 + 异步逻辑未等待
- 你没有给
useEffect传入第二个依赖数组参数,这会导致每次App组件渲染完成后都会反复执行这个useEffect。你在useEffect内修改loading状态会触发组件重渲染,重渲染后又会再次执行useEffect修改loading,自然会形成无限循环。 loadResults是异步拉取数据的逻辑,但你现在是同步调用,相当于刚把loading设为true,立刻就执行了设为false的dispatch,React的状态批量更新机制会合并这两次状态变更,最终渲染时只会用最后一次的false状态,这也是你能打印到状态变化但看不到UI更新的原因。
核心问题2:子组件存在冗余状态
子组件不需要额外用useState+useEffect存储按钮文本,直接通过props计算即可,减少不必要的状态监听逻辑。
修正后代码
App组件
import { useReducer, useEffect } from 'react'; import SampleComponent from './SampleComponent'; const App = () => { const [state, stateDispatch] = useReducer(stateReducer,{loading: false}) // 空依赖数组表示仅在组件挂载时执行一次拉取 // 如果需要依赖特定变量触发拉取(比如搜索词、页码),把对应变量加到依赖数组即可 useEffect(() => { const fetchData = async () => { stateDispatch({type:'loadingResults'}); // 等待异步拉取完成再修改加载状态 await loadResults(); stateDispatch({type:'finishedLoadingResults'}); } fetchData(); }, []); return ( <SampleComponent loading={state.loading} getBooks={getBooks} /> ); } const stateReducer = (prevState,action) => { switch(action.type) { case 'loadingResults': return {...prevState, loading:true}; case 'finishedLoadingResults': return {...prevState, loading: false}; default: throw new Error(); } }
子组件
const SampleComponent = (props) => { // 直接通过props计算按钮文本,无需额外状态 const buttonText = props.loading ? 'Loading...' : 'Load More'; return ( <div onClick={(event) => props.getBooks(event,false)} className="moreResults">{buttonText}</div> ) }
内容的提问来源于stack exchange,提问作者codedude
相关产品推荐
相关产品推荐

