React中useReducer结合useContext使用时,页面刷新后子组件state.map内容空白的问题求助
解决刷新页面后产品不渲染的问题
我看了你的代码,发现两个关键问题导致刷新后产品区域空白,点击复选框后又正常:
1. 初始数据加载逻辑错误
在App组件里,你通过fetchInitialBoiler获取初始产品数据,但这个函数是异步的——当useReducer初始化时,fetch请求还没完成,返回的initBoilers是空数组。而之后fetch完成后,你没有通过dispatch更新useReducer的state,所以页面首次渲染时state为空,自然没有产品显示。当你点击复选框时,dispatch了其他动作触发state更新,产品才会正常渲染。
修复方案:
把初始数据的获取放到useEffect里,当fetch完成后,dispatch一个初始化动作来设置state:
修改App组件:
function App () { const [count, setCount] = useState(0) const [prev, setPrev] = useState([]) // 先初始化state为空数组 const [state, dispatch] = useReducer(reducer, []) // 用useEffect执行初始数据获取 useEffect(() => { async function loadInitialBoilers() { try { const response = await fetch('http://localhost:9000/boilers') const data = await response.json() // dispatch初始化动作 dispatch({ type: 'INIT', payload: data }) } catch (err) { console.error('加载产品数据失败:', err) } } loadInitialBoilers() }, []) function reducer (state, action) { let current switch (action.type) { // 添加INIT case来处理初始数据 case 'INIT': return action.payload case 'DISPONIBILI': current = state.filter(item => item.disponibile) // 简化filter逻辑 setPrev(current) return current case 'PROMO': current = state.filter(item => item.inSconto) setPrev(current) return current // ...其他case保持不变,记得把所有filter里的三元表达式简化,比如直接写`item.hasOwnProperty('brand') && item.brand === 'Ariston'` default: return state } } // ...其余代码不变 }
2. React列表key的位置错误
在CardProduct组件的returnCardProduct函数里,你把key={i}放在了内部的<div className="card">元素上,但React要求key必须是map返回的最外层元素的属性。如果key位置不对,React无法正确跟踪列表项的变化,可能导致即使state有数据,也无法正常渲染。
修复方案:
把key移到map返回的最外层<div className="row">上:
function returnCardProduct () { return ( state.map((item, i) => { const { brand, descrizione, prezzo, note, stelle } = item return ( // key放在map返回的最外层元素上 <div className="row" key={i}> <div className="colcard"> <div className="card" style={{ width: 'auto', height: 'auto' }}> <Hearty/> <img className="card-img-top" src={ boiler } alt="boiler"/> <div className="card-body"> <p className="card-title"> { brand.toUpperCase() }</p> <h6 className="card-text">{ descrizione }</h6> <Star stelle={ stelle }/> <h4> { prezzo } </h4> <h5> { note } </h5> <Confronta count={ count } setCount={ setCount }/> </div> </div> </div> </div> ) })) }
额外优化建议
- Filters组件里的计数逻辑有问题,比如
{stock.map((item) => item.disponibili )}会把所有disponibili的值拼接成字符串,改成统计数量更合理:{stock.filter(item => item.disponibili).length} - reducer里的filter逻辑可以简化,比如
item.disponibile ? item : null直接写成item.disponibile,因为filter会自动保留truthy的元素。
做完这些修改后,刷新页面应该就能正常显示产品了。
内容的提问来源于stack exchange,提问作者mcdev84it
相关产品推荐
相关产品推荐

