React Hooks实现动态触发:为每条服务端数据添加独立状态
解决React每条数据独立状态控制的问题
嘿,我来帮你搞定这个每条数据独立控制显示状态的需求!先看看你现有代码里的几个关键问题:
- 你在渲染逻辑里直接调用
setPanduan,这会触发无限重渲染(因为setState会导致组件重新渲染,渲染又调用setState) - 当前的
panduan状态结构没法对应每条数据的独立状态,数组形式很难精准控制某一条的显示/隐藏
下面是针对你的需求的完整解决方案:
核心思路
我们需要给每条从服务端获取的数据绑定一个唯一标识(比如每条数据自带的id),用这个标识来跟踪该条数据的展开/收起状态。推荐用对象类型的状态来存储,键是数据的id,值是布尔值(true表示显示,false表示隐藏),这样能精准控制每一条的状态。
修改后的完整代码
function RekapAngkatan({ auth, getProposalRecapByYear, getReportRecapByYear, posts, StickyNav }) { const postingan = posts.posts; // 用对象存储每条数据的展开状态,键是post的id,值是布尔值 const [expandedItems, setExpandedItems] = React.useState({}); const [loading, setLoading] = React.useState(true); // 补全你之前缺失的loading状态定义 React.useEffect(() => { const fetchData = async () => { if (auth.isAuthenticated) { try { // 并行请求两个接口,提升加载效率 await Promise.all([ getProposalRecapByYear(), getReportRecapByYear() ]); } catch (err) { console.error('数据请求失败:', err); } finally { setLoading(false); // 请求完成后结束加载状态 } } }; fetchData(); }, [auth, getProposalRecapByYear, getReportRecapByYear]); // 切换指定id数据的展开/收起状态 const toggleItem = (postId) => { setExpandedItems(prevState => ({ ...prevState, [postId]: !prevState[postId] // 对指定id的状态取反 })); }; if (loading) { return <Loading />; } // 渲染每条数据 return postingan.data.map((post) => { // 必须用post的唯一id作为key,不要用index,避免渲染异常 return ( <Section bg="transparent" margin="0 1.5em" padding="0 2em" key={post.id}> <div className="info-color"> {post.value} <FakeButton bg="#8C489F" type="button" onClick={() => toggleItem(post.id)} > {/* 根据当前状态切换按钮文字 */} {expandedItems[post.id] ? 'Caret Up' : 'Caret Down'} </FakeButton> {/* 根据对应id的状态控制属性组件的显示 */} {expandedItems[post.id] && ( <Attribute> {/* 这里渲染你需要的proposal和laporan akhir属性 */} <div>Proposal: {post.proposal}</div> <div>Laporan Akhir: {post.laporanAkhir}</div> <div>Amount: {post.amount}</div> </Attribute> )} </div> </Section> ); }); }
关键修改点说明
- 状态结构优化:把原来的数组状态
panduan改成对象expandedItems,每条数据的id作为键,这样能精准定位到某一条的状态。 - 避免无限重渲染:移除了渲染逻辑里的
setPanduan调用,所有状态更新都放在toggleItem函数里,只有点击按钮时才触发。 - 请求逻辑优化:用
Promise.all并行请求两个接口,统一处理加载状态,避免重复请求。 - key的正确使用:用数据的唯一
id作为map的key,而不是index,这是React性能优化和避免渲染错误的最佳实践。 - 状态切换逻辑:使用函数式更新
setExpandedItems(prevState => ...),确保每次状态更新都是基于最新的状态值,避免闭包陷阱。
额外提示
- 如果你的数据里没有
id字段,可以用其他唯一标识(比如value或者组合字段),只要保证每条数据的标识唯一就行。 - 如果需要默认展开某些条目,可以在初始化状态的时候设置,比如
const [expandedItems, setExpandedItems] = React.useState({ 1: true, 3: true });(假设id为1和3的条目默认展开)。
内容的提问来源于stack exchange,提问作者panji gemilang
相关产品推荐
相关产品推荐

