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

React报错:'children'未定义,按钮批量显示文本功能开发遇阻

问题:React循环按钮的状态初始化错误与功能实现

我想实现点击按钮时,循环中的每个按钮切换显示对应文本的功能。一开始用useState创建状态:

const [CouponCode, setCouponCode] = useState(Array.from({length:children.length}).fill(false))

但出现了children未定义的错误;尝试换成this.props.children.length后,又出现了props相关的错误。

附上相关代码:

import React,{useState,useEffect} from 'react';
import axios from"axios";
import Card from '@mui/material/Card';
import { Box, Grid, ListItemText } from '@mui/material';

function FetchData(props) {
  const [records, setRecords] = useState([]);
  const [CouponCode, setCouponCode] = useState(Array.from({length:children.length}).fill(false))

  useEffect(() => {
    axios({
      method: "GET",
      url: "http://127.0.0.1:5000/coupons",
      headers: {},
      params: {},
    })
      .then((response) => {
        console.log("response :", response.data);
        setRecords(response.data);
      })
      .catch((error) => {
        console.log(error);
      });
  }, []);

  return (
    <div styles={{padding:30}}>
      <Grid container spacing={8} justifyContent="center">
        {records?.map((list,index)=>(
          <Grid item xs={10} key={index}>
            <Card variant='outlined'sx={{display:"block",width:"70vw"}}>
              <Box sx={{ width: '95px', height: '100px', boxShadow: 0, 
            margin: '10px',top:"0" }}>
              <img width="95px" height="100px" alt='Logo' srcSet={list.title_logo}/>
              <ListItemText
              sx={{display:"inline",position:"absolute"}}
              primaryTypographyProps={{fontSize:"2rem"}}
              secondaryTypographyProps={{fontSize:"1.1rem",style: {
                whiteSpace: 'wrap',
                overflow: 'hidden',
                textOverflow: 'ellipsis'}}}
              primary={<div><span>{list.offer_title}</span></div>}
              secondary={list.description}/>
              
              {list.type_of_voucher==="Coupons"? 
              <button onClick={()=> setCouponCode(prevState => {
                const tutorsArr = [...prevState];
                tutorsArr[index] = !tutorsArr[index]
                return tutorsArr;})}>{CouponCode[index] ? "Get Coupon Code":""}</button>
              :<button style={{display:'inline-flex',float:'right'}} onClick={()=> setCouponCode(prevState => {
                const tutorsArr = [...prevState];
                tutorsArr[index] = !tutorsArr[index]
                return tutorsArr;})}>{CouponCode[index] ?"Get Deals":""} </button>}

            </Box>
            </Card>
          </Grid>
        ))};
      </Grid>
    </div>
  );
};

export default FetchData;

解决方案

1. 错误原因

  • 组件内未定义children变量,你实际需要的是接口返回的records数组长度,而非组件子元素。
  • 函数组件不能使用this.props,需直接用参数props,但这里props.children并非你需要的内容。
  • 组件初始化时records是空数组,直接用长度初始化状态会导致逻辑异常。

2. 修复步骤

(1)初始化状态为空数组

将CouponCode的初始化改为空数组,避免依赖未定义的变量:

const [CouponCode, setCouponCode] = useState([]);

(2)监听records变化,动态同步状态长度

添加useEffect监听records的更新,当接口返回数据后,同步调整CouponCode数组的长度,确保和records条目数一致:

useEffect(() => {
  // 当records获取到数据后,初始化状态数组,每个元素默认false
  setCouponCode(Array.from({ length: records.length }).fill(false));
}, [records]);

(3)调整按钮文本逻辑(可选)

你当前的按钮文本逻辑是状态为true时显示文本,false时为空,如果想实现「默认显示按钮文案,点击后切换为对应内容」的效果,可以修改为:

// 优惠券按钮
<button onClick={()=> setCouponCode(prevState => {
  const tutorsArr = [...prevState];
  tutorsArr[index] = !tutorsArr[index];
  return tutorsArr;
})}>
  {CouponCode[index] ? list.coupon_code : "Get Coupon Code"}
</button>

// 优惠活动按钮
<button style={{display:'inline-flex',float:'right'}} onClick={()=> setCouponCode(prevState => {
  const tutorsArr = [...prevState];
  tutorsArr[index] = !tutorsArr[index];
  return tutorsArr;
})}>
  {CouponCode[index] ? "查看活动详情" : "Get Deals"}
</button>

3. 完整修复后的代码

import React,{useState,useEffect} from 'react';
import axios from"axios";
import Card from '@mui/material/Card';
import { Box, Grid, ListItemText } from '@mui/material';

function FetchData(props) {
  const [records, setRecords] = useState([]);
  const [CouponCode, setCouponCode] = useState([]);

  useEffect(() => {
    axios({
      method: "GET",
      url: "http://127.0.0.1:5000/coupons",
      headers: {},
      params: {},
    })
      .then((response) => {
        console.log("response :", response.data);
        setRecords(response.data);
      })
      .catch((error) => {
        console.log(error);
      });
  }, []);

  // 监听records变化,同步更新CouponCode数组长度
  useEffect(() => {
    setCouponCode(Array.from({ length: records.length }).fill(false));
  }, [records]);

  return (
    <div style={{padding:30}}>
      <Grid container spacing={8} justifyContent="center">
        {records?.map((list,index)=>(
          <Grid item xs={10} key={index}>
            <Card variant='outlined'sx={{display:"block",width:"70vw"}}>
              <Box sx={{ width: '95px', height: '100px', boxShadow: 0, 
            margin: '10px',top:"0" }}>
              <img width="95px" height="100px" alt='Logo' srcSet={list.title_logo}/>
              <ListItemText
              sx={{display:"inline",position:"absolute", marginLeft: 10}}
              primaryTypographyProps={{fontSize:"2rem"}}
              secondaryTypographyProps={{fontSize:"1.1rem",style: {
                whiteSpace: 'wrap',
                overflow: 'hidden',
                textOverflow: 'ellipsis',
                width: '60vw'
              }}}
              primary={<div><span>{list.offer_title}</span></div>}
              secondary={list.description}/>
              
              {list.type_of_voucher==="Coupons"? 
              <button onClick={()=> setCouponCode(prevState => {
                const tutorsArr = [...prevState];
                tutorsArr[index] = !tutorsArr[index];
                return tutorsArr;
              })}>
                {CouponCode[index] ? list.coupon_code : "Get Coupon Code"}
              </button>
              :<button style={{display:'inline-flex',float:'right'}} onClick={()=> setCouponCode(prevState => {
                const tutorsArr = [...prevState];
                tutorsArr[index] = !tutorsArr[index];
                return tutorsArr;
              })}>
                {CouponCode[index] ? "查看活动详情" : "Get Deals"}
              </button>}

            </Box>
            </Card>
          </Grid>
        ))};
      </Grid>
    </div>
  );
};

export default FetchData;

内容的提问来源于stack exchange,提问作者Shivam Misra

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.13 01:40:55