React点击菜谱跳转报错:'obj' is not defined.eslint no-undef
解决React中
obj is not defined的错误方案 问题根源
- 你先把包含菜谱数据的数组
displayMatchedRecipe映射成了JSX片段数组list,之后再对list做遍历,此时每个迭代项是JSX元素而非原始菜谱数据对象,因此在onClick中访问obj会出现未定义错误。 onClick={clickFn(obj.recipe)}的写法会在组件渲染时直接执行clickFn,而非点击时触发,这也是错误的事件绑定方式。
修复步骤
1. 重构数据渲染逻辑
删除单独定义的list变量,直接在return的Card循环中遍历displayMatchedRecipe,这样每个循环项都是原始的菜谱数据obj,可以直接访问obj.recipe。
2. 修正onClick事件绑定
用箭头函数包裹clickFn调用,确保点击时才执行函数,并传入正确的obj.recipe参数。
修复后的完整代码
import { data } from '../utils/data'; import { TextInput } from '../components/ui/TextInput'; import { useState } from 'react' import { Flex, Card, CardBody, Center, Text, Image, Stack, Tag, Heading, } from '@chakra-ui/react'; export const RecipeListPage = ({ clickFn }) => { const [searchField, setSearchField] = useState(''); const handleChange = (event) => { setSearchField(event.target.value); }; const matchedRecipe = data.hits.filter(obj => obj.recipe.label.toLowerCase().includes(searchField.toLowerCase())); let displayMatchedRecipe = data.hits; if (matchedRecipe.length > 0) { displayMatchedRecipe = matchedRecipe; } return ( <> <Center bg='pink.600' flexDir="column" h='100%' > <Heading size='xl' mt={2} color='white'>Winc Recipe Checker</Heading> <TextInput changeFn={handleChange} matchedRecipe={matchedRecipe} /> <Flex wrap='wrap' gap={8} justify='center' my={2} > {/* 直接遍历原始数据数组,获取完整的obj对象 */} {displayMatchedRecipe.map((obj) => ( <Card bgColor='white' overflow='hidden' borderRadius={15} h='md' w='xsm' cursor='pointer' _hover={{ transform: 'scale(1.03)' }} key={obj.recipe.label} {/* 使用唯一标识作为key */} onClick={() => clickFn(obj.recipe)} {/* 箭头函数包裹,点击时触发 */} > <CardBody w='18em' p={0} > <Stack direction='column' spacing='2px'> <Image src={obj.recipe.image} h='10rem' w='100%' mt={-1} borderTopLeftRadius={15} borderTopRightRadius={15} objectFit='cover' /> <Flex flexDirection='column' align='center' gap={1}> <Text textTransform='uppercase'> {obj.recipe.mealType} </Text> <Text fontSize={18} fontWeight='bold' textAlign='center' > {obj.recipe.label} </Text> <Flex gap={1}> {obj.recipe.healthLabels.filter( label => label.includes('Vegetarian')).map(filteredLabel => ( <Tag key={filteredLabel} textTransform='uppercase' fontSize={10} bgColor='yellow.400' color='gray.900' > Vegetarian </Tag> ))} {obj.recipe.healthLabels.filter( label => label.includes('Vegan')).map(filteredLabel => ( <Tag key={filteredLabel} textTransform='uppercase' fontSize={10} bgColor='yellow.400' color='gray.900' > Vegan </Tag> ))} </Flex> <Flex gap={2} justify='center' wrap='wrap'> {obj.recipe.dietLabels.map((dietLabels) => ( <Tag key={dietLabels} textTransform='uppercase' fontSize={10} bgColor='green.400' color='gray.900' > {dietLabels} </Tag> ))} </Flex> <Text textTransform='capitalize'> Dish: {obj.recipe.dishType} </Text> <Flex justify='center' gap={2} wrap='wrap'> <> {obj.recipe.cautions.length> 0 && <Text>Cautions: </Text>} {obj.recipe.cautions.map((cautions) => ( <Tag key={cautions} {/* 修正key为当前项,确保唯一性 */} textTransform='uppercase' fontSize={10} bgColor='purple.400' color='gray.800' > {cautions} </Tag> ))} </> </Flex> </Flex> </Stack> </CardBody> </Card> ))} </Flex> </Center> </> ); };
额外优化点
- 将
key值改为obj.recipe.label(唯一标识),避免使用整个对象或JSX作为key的潜在问题。 - 修正了
cautions映射时的key值,从obj.recipe.cautions改为cautions,确保每个key唯一。
内容的提问来源于stack exchange,提问作者Sahdia
相关产品推荐
相关产品推荐

