React Redux map循环点击触发所有onSelectProject执行问题
问题背景
- 组件内定义了
onClick事件处理逻辑,预期点击时触发mapDispatchToProps中的onSelectProject方法,向store派发action,传入被点击项目对应的id。 - 异常表现:页面渲染后/单次点击时,
onSelectProject会为列表内所有项目各执行一次,10个项目的列表会在控制台打印10次id日志。
附问题代码(index.js / ProjectComponent)
export function ProjectComponent({ selectedProject, projects, onSelectProject, onGetProjects, }) { useInjectReducer({ key, reducer }); useInjectSaga({ key, saga }); useEffect(() => { onGetProjects(); }, []); return ( { projects.map((project, index) => { return <ul key={project.id} className="project"> <li>{project.name}</li> <li>{project.createdAt}</li> <li><a onClick={onSelectProject(project.id)} href="#" title="Preview this Project"><img src={view_icon} alt="view through icon"/></a></li> </ul> })} ); } const mapStateToProps = createStructuredSelector({ projects: makeSelectProjects(), selectedProject: makeSelectProject() }); export function mapDispatchToProps(dispatch) { return { onSelectProject: (id) => { console.log(id); dispatch(selectProject(id)); }, // 原代码此处缺失逗号,会触发语法错误 onGetProjects: () => { dispatch(getProjects()); } }; } const withConnect = connect( mapStateToProps, mapDispatchToProps, ); export default compose( withConnect, )(ProjectComponent);
问题原因
核心错误出在onClick的事件绑定写法:
代码中写的是onClick={onSelectProject(project.id)},这种写法会在组件渲染、遍历projects列表的阶段,直接执行每一项对应的onSelectProject(project.id)调用,根本不会等用户点击才触发。
React的事件属性需要接收一个函数引用作为回调,等点击事件触发时React才会调用这个函数;直接写函数执行语句,相当于渲染时就把所有项的方法全跑了一遍,这就是10个项目会打印10次日志的根本原因,和点击操作本身没有关系,甚至不做点击操作,页面渲染完日志就已经全部打印出来了。
修复方案
把事件绑定改成传入箭头函数包裹的形式,点击触发时才执行方法传参即可:
// 把原来的onClick绑定替换成下面的写法 <li> <a onClick={() => onSelectProject(project.id)} href="#" title="Preview this Project" > <img src={view_icon} alt="view through icon"/> </a> </li>
如果不想写行内箭头函数,也可以把onSelectProject改写成柯里化函数,提前接收id参数后返回点击时要执行的回调,两种写法效果一致。
内容的提问来源于stack exchange,提问作者Jebathon
相关产品推荐
相关产品推荐

