React中如何跨两级组件传递带ID参数的handleClick函数?
React跨两级组件传递带参数回调的修复方案
核心问题总结
需要将顶层App组件的handleClick回调向下传递两级(到Main再到动态渲染的Answer),实现点击Answer时把对应的answerId传回App以更新状态。现有代码的两个关键错误导致无法实现该功能:
- App传递给Main的
handleClick未正确关联顶层回调,且未预留参数传递入口 - Main组件中调用的
handleClick不是App传入的props回调,而是未定义的函数
修正后的完整代码
App组件
import { useState } from 'react'; import Main from './Main'; function App() { const [triviaData, setTriviaData] = useState([]); // 从API获取试题数据 // 顶层回调:接收answerId并更新状态 function handleClick(answerId) { console.log('点击的选项ID:', answerId); // 示例状态更新逻辑:切换对应选项的isClicked状态 setTriviaData(prevData => prevData.map(question => ({ ...question, answers: question.answers.map(answer => answer.answerId === answerId ? {...answer, isClicked: !answer.isClicked} : answer ) })) ); } const triviaElements = triviaData.map(item => ( <Main item={item} key={item.id} handleClick={handleClick} // 直接传递顶层回调,无需提前绑定参数 /> )); return ( <div>{triviaElements}</div> ); } export default App;
Main组件
import Answer from './Answer'; export default function Main(props) { const triviaAnswers = props.item.answers.map(item => ( <Answer key={item.answerId} answer={item.answer} isCorrect={item.isCorrect} answerId={item.answerId} // 使用App传入的回调,绑定当前选项的answerId handleClick={() => props.handleClick(item.answerId)} /> )); return( <section className="main"> <h2 className="main--question">{props.item.question}</h2> {triviaAnswers} </section> ); }
Answer组件(无需修改)
export default function Answer(props) { return ( <div className="answer" onClick={props.handleClick}>{props.answer}</div> ); }
可选优化:用useCallback减少不必要重渲染
如果triviaData频繁更新,每次渲染App时都会创建新的handleClick函数,导致Main和Answer组件重复渲染。可以用useCallback缓存回调函数:
import { useState, useCallback } from 'react'; // ... const handleClick = useCallback((answerId) => { console.log('点击的选项ID:', answerId); setTriviaData(prevData => prevData.map(question => ({ ...question, answers: question.answers.map(answer => answer.answerId === answerId ? {...answer, isClicked: !answer.isClicked} : answer ) })) ); }, []); // 依赖项为空,因为setTriviaData是useState返回的稳定函数
内容的提问来源于stack exchange,提问作者lordpotato89
相关产品推荐
相关产品推荐

