React:如何在状态切换函数中用展开运算符实现单个元素独立状态控制
问题原因
你当前仅声明了一个全局共享的布尔状态 toggleButton,所有通过 map 渲染出来的按钮都依赖这同一个状态判断展示内容,修改状态自然会同步触发所有按钮的切换。
解决方案
方案1:父组件存储所有条目状态(用到你提到的展开运算符)
把状态改为对象格式,以歌曲id为key存储对应条目的按钮状态,修改时只更新对应id的状态值即可:
export default function App() { // 初始状态为空对象,默认所有按钮初始状态为PLAY const [toggleStatus, setToggleStatus] = useState({}); // 点击时传入对应歌曲id const handleClick = (songId) => { setToggleStatus(prev => ({ ...prev, // 展开旧状态,保留其他条目的状态不变 [songId]: !prev[songId] ?? true // 仅修改当前点击条目的状态,首次点击默认取反初始值true })); }; return ( <div className="App"> <h1>SONGS</h1> <div className="container"> {songs.map((song) => { return ( <div className="song-container" key={song.id}> <h4>{song.name}</h4> {/* 仅判断当前歌曲id对应的状态 */} {toggleStatus[song.id] ?? true ? ( <button onClick={() => handleClick(song.id)}>PLAY</button> ) : ( <button onClick={() => handleClick(song.id)}>STOP</button> )} </div> ); })} </div> </div> ); }
方案2:拆分独立子组件(更推荐)
把单条歌曲的逻辑封装为独立子组件,每个子组件内部维护自己的按钮状态,互相完全隔离,不需要在父组件处理复杂的状态合并逻辑:
// 独立歌曲条目子组件 function SongItem({ song }) { const [toggleButton, setToggleButton] = useState(true); const handleClick = () => setToggleButton(!toggleButton); return ( <div className="song-container"> <h4>{song.name}</h4> {toggleButton ? ( <button onClick={handleClick}>PLAY</button> ) : ( <button onClick={handleClick}>STOP</button> )} </div> ) } // 父组件仅负责渲染列表 export default function App() { return ( <div className="App"> <h1>SONGS</h1> <div className="container"> {songs.map((song) => <SongItem key={song.id} song={song} />)} </div> </div> ); }
内容的提问来源于stack exchange,提问作者Afx Crush
相关产品推荐
相关产品推荐

