React组件传递函数字典报错:无法读取undefined的select属性
问题分析与解决
我在App组件中定义了SelectCard和DiscardCard两个函数,随后将这两个函数以对象形式通过onPress属性传递给Card组件,代码如下:
<Card key={el.key} item={el} onPress={{ select: () => SelectCard(el.key), discard: () => DiscardCard(el.key) }} />
但在Card组件中尝试通过props.onPress.select访问该函数时,出现了如下错误:
react-dom.development.js:18687 The above error occurred in the <Card> component: at Card (http://localhost:5174/src/components/Card.jsx?t=1670102247232:33:48) at div at div at div at App (http://localhost:5174/src/App.jsx?t=1670102247232:24:31) react-dom.development.js:26923 Uncaught TypeError: Cannot read properties of undefined (reading 'select') at Card (Card.jsx:28:32) at renderWithHooks (react-dom.development.js:16305:18) at mountIndeterminateComponent (react-dom.development.js:20074:13) at beginWork (react-dom.development.js:21587:16) at beginWork$1 (react-dom.development.js:27426:14) at performUnitOfWork (react-dom.development.js:26557:12) at workLoopSync (react-dom.development.js:26466:5) at renderRootSync (react-dom.development.js:26434:7) at recoverFromConcurrentError (react-dom.development.js:25850:20) at performConcurrentWorkOnRoot (react-dom.development.js:25750:22)
完整代码
App组件
import { useState } from 'react' import reactLogo from './assets/react.svg' import Card from './components/Card' import data from "./assets/data.json" import {nanoid} from "nanoid" function App() { const [people, setPeople] = useState(data['people'].map( el=>{ return { ...el, 'key' : nanoid(), } } )) const [myCard, setMyCard] = useState( { "name":"Name and Surname", "img":"https://i.picsum.photos/id/1070/200/300.jpg?hmac=dJNTYlLwT_0RupxbJNbw5Wj-q2cCTB4Xh-GqWRofIIc", "description": "This is a silly descriptionhis is a silly descriptionhis is a silly description", 'key' : nanoid(), "selected":false, "active":true, } ) function SelectCard(CardKey){ console.log('SelectCard') setPeople(oldPeople=>{ return oldPeople.map(el=>{ return el.key === CardKey ? { ...el, 'state': el.state === 'active'?'selected': 'active'} : { ...el, 'state':'active'} }) }) } function DiscardCard(CardKey){ console.log('DiscardCard') setPeople(oldPeople=>{ return oldPeople.map(el=>{ return el.key === CardKey ? { ...el, 'state': el.state === 'discarded'?'active': 'discarded'} : { ...el} }) }) } const cards = people.map(el=>{ return <Card key = {el.key} item={el} onPress={{ select : ()=>SelectCard(el.key), discard : ()=>DiscardCard(el.key) }} /> }) return ( <div className="App"> <div className='container'> <div className='left'> <div className='cards'> {cards} </div> </div> <div className = 'right'> <h4>You are: </h4> <Card key = {myCard.key} item={myCard}/> </div> </div> </div> ) } export default App
Card组件
import { useState } from 'react' function Card(props) { //const [count, setCount] = useState(0) function getClassName(state) { switch (state) { case "active": return ""; case "selected": return "overlay-selected"; case "discarded": return "overlay-discarded"; case "complete": return "overlay-complete"; default: return ""; } } const className = `card ${getClassName(props.item.state)}` return ( <div className={className} onClick={props.onPress.select}> <img className='card-img' alt='Card Image' src={props.item.img} /> <h3 className='card-title'>{props.item.name} </h3> { props.item.state === 'selected' ? <div className='card-cta'> <button className='btn btn-back' onClick={ props.item.selected ? (event)=> { props.onPress.select //event.stopPropagation() } : ()=>{}} >Back</button> <button className='btn btn-discard' onClick={ (event) =>{ //event.stopPropagation() props.onPress.discard console.log('called me') } } >Discard</button> </div> : <p className='card-description'>{props.item.description} </p> } </div> ) } export default Card
错误原因
- 缺失
onPress属性传递:在App组件右侧区域渲染myCard对应的Card组件时,没有传入onPress属性,导致该Card实例的props.onPress为undefined,访问props.onPress.select时直接抛出TypeError。 - 函数未实际调用:Card组件按钮的点击事件中,仅引用了函数(如
props.onPress.select),但未执行函数,需要通过()触发调用。
解决方案
1. 给右侧Card补充onPress属性
如果右侧Card不需要操作逻辑,可传入空对象作为默认值;如果需要对应逻辑,传入针对myCard的处理函数:
// 示例:传入空对象避免报错 <Card key={myCard.key} item={myCard} onPress={{select: () => {}, discard: () => {}}}/>
2. 修复函数调用问题
在Card组件的按钮点击事件中,将函数引用改为调用形式:
// Back按钮 <button className='btn btn-back' onClick={props.item.selected ? (event) => { props.onPress.select(); // 加上()执行函数 // event.stopPropagation() } : () => {}} >Back</button> // Discard按钮 <button className='btn btn-discard' onClick={(event) => { // event.stopPropagation() props.onPress.discard(); // 加上()执行函数 console.log('called me') }} >Discard</button>
3. 可选:给Card组件设置props默认值
为避免后续未传属性导致的报错,可在Card组件中设置默认props:
function Card(props) { // 解构时设置默认值 const { onPress = { select: () => {}, discard: () => {} }, item } = props; // ... 其他代码 } // 或者使用defaultProps Card.defaultProps = { onPress: { select: () => {}, discard: () => {} } };
内容的提问来源于stack exchange,提问作者giaggi
相关产品推荐
相关产品推荐

