You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

React点击菜谱跳转报错:'obj' is not defined.eslint no-undef

解决React中obj is not defined的错误方案

问题根源

  1. 你先把包含菜谱数据的数组displayMatchedRecipe映射成了JSX片段数组list,之后再对list做遍历,此时每个迭代项是JSX元素而非原始菜谱数据对象,因此在onClick中访问obj会出现未定义错误。
  2. 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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.12 04:17:34