传递给子组件时道具未定义(反应挂钩)

Props is undefined when passed to a child component (react hooks)

我正在构建一个简单的议程组件,运行 成为一个问题。这个想法是,当一个人点击这一天,然后看到这一天的培训。我的逻辑如下

  1. 单击按钮时我将状态设置为日期 id
  2. 在现有活动项上,三元运算符呈现组件
  3. 我将函数调用作为 props 传递,returns 是最新的对象。

我尝试将函数调用置于 handleClick 函数中,但没有帮助。对我来说,问题似乎是函数没有及时返回组件传递它的值,但我不知道如何绕过这个问题。 这是包含所有内容的 codesandbox - 请帮忙

https://codesandbox.io/s/cranky-johnson-s2dj3?file=/src/scheduledTrainingCard.js

这是父组件的代码,因为问题出在这里

import React, { useState } from "react";
import { Transition, Grid, Button, Container } from "semantic-ui-react";
import ScheduledTrainingCard from "./scheduledTrainingCard";

function ScheduleComponent(props) {
  const days = [
    {
      id: "1",
      dayTrainings: [
        {
          time: "20:15:00",
          training: "zumba",
          trainer: "joe"
        },
        {
          time: "16:00:00",
          training: "stretching",
          trainer: "lily"
        }
      ],
      date:
        "Thu Dec 28 1995 00:00:00 GMT+0100 (Central European Standard Time)",
      createdAt: "2021-07-14T19:30:59.177Z"
    },
    {
      id: "2",
      dayTrainings: [
        {
          time: "23:15:00",
          training: "boxing",
          trainer: "phoebe"
        },
        {
          time: "15:00:00",
          training: "dancing",
          trainer: "kate"
        }
      ],
      date: "Thu Sep 23 2021 20:57:38 GMT+0200 (Central European Summer Time)",
      createdAt: "2021-09-23T19:01:53.801Z"
    },
    {
      id: "3",
      dayTrainings: [
        {
          time: "23:15:00",
          training: "ballet",
          trainer: "nataly"
        },
        {
          time: "12:00:00",
          training: "crossfit",
          trainer: "sheldon"
        }
      ],
      date: "Fri Jul 23 2021 21:02:37 GMT+0200 (Central European Summer Time)",
      createdAt: "2021-09-23T19:03:31.161Z"
    }
  ];

  const [activeItem, setActiveItem] = useState("");

  const handleItemClick = (e) => {
    setActiveItem(e.target.name);
  };

  function showSelectedDay(arr, dayId) {
    arr.forEach((element, index) => {
      if (dayId === element.id) {
        console.log("selected day is " + element.date);
        let trainings = element.dayTrainings;
        trainings.map((training) => {
          return training;
        });
      } else {
        console.log("not selected, day id is " + element.id);
      }
    });
  }

  const ScheduleComponent = (
      <Container style={{ textAlign: "left" }}>
        <h1 style={{ textAlign: "center" }}>Training Schedule</h1>
        <p>
          Lorem ipsum dolor sit amet consectetur adipisicing elit. Incidunt
          dolor unde repudiandae culpa ullam, asperiores officiis ratione
          repellat quaerat nihil vel corporis distinctio vero doloribus dolore
          optio commodi voluptatum inventore.
        </p>

        <Container>
          <Grid style={{ margin: "2rem auto", textAlign: "center" }} relaxed>
            <Button onClick={(e) => handleItemClick(e)} name={"1"}>
              Monday
            </Button>
            <Button onClick={(e) => handleItemClick(e)} name={"2"}>
              Tuesday
            </Button>
            <Button onClick={(e) => handleItemClick(e)} name={"3"}>
              Wednesday
            </Button>
          </Grid>
        </Container>
        <Container>
          {activeItem && (
            <ScheduledTrainingCard
              dayTraining={showSelectedDay(days, activeItem)}
            ></ScheduledTrainingCard>
          )}
        </Container>
      </Container>
   
  );
  return ScheduleComponent;
}

export default ScheduleComponent;

你可以做到

const handleItemClick = (e) => {
    days.map(item => {
      if(item.id === e.target.name){
        setActiveItem(item)
      }
    })
  };

并更改此行

{activeItem && 
          activeItem.dayTrainings.map(day => <ScheduledTrainingCard dayTraining={day}/>)
          }

首先为selectedDays定义一个新状态:

  const [activeItem, setActiveItem] = useState("");
  const [selectedDays, setSelectedDays] = useState([]);

然后根据用户的选择为 setSelectedDaysactiveItem 设置值:

  useEffect(() => {
    let filteredDays = days.filter((x) => x.id === activeItem);
    setSelectedDays(filteredDays);
  }, [activeItem]);

终于定义了一个新函数来渲染日子。因为days是层级数组,需要循环两次:

  const showDays = () => {
    return selectedDays.map((days, index) => {
      return days.dayTrainings.map((item, i) => {
        let dayTraining = {
          id: days.id,
          time: item.time,
          trainer: item.trainer,
          training: item.training
        };
        return (
          <ScheduledTrainingCard
            dayTrainings={dayTraining}
          ></ScheduledTrainingCard>
        );
      });
    });
  };

const ScheduleComponent = (
    <Transition.Group>
      <Container style={{ textAlign: "left" }}>
        <h1 style={{ textAlign: "center" }}>Training Schedule</h1>
        <p>
          Lorem ipsum dolor sit amet consectetur adipisicing elit. Incidunt
          dolor unde repudiandae culpa ullam, asperiores officiis ratione
          repellat quaerat nihil vel corporis distinctio vero doloribus dolore
          optio commodi voluptatum inventore.
        </p>

        <Container>
          <Grid style={{ margin: "2rem auto", textAlign: "center" }} relaxed>
            <Button onClick={(e) => handleItemClick(e)} name={1}>
              Monday
            </Button>
            <Button onClick={(e) => handleItemClick(e)} name={2}>
              Tuesday
            </Button>
            <Button onClick={(e) => handleItemClick(e)} name={3}>
              Wednesday
            </Button>
          </Grid>
        </Container>
        <Container>{activeItem && selectedDays && showDays()}</Container>
      </Container>
    </Transition.Group>
  );
  return ScheduleComponent;

问题是您在地图内部使用 return。 看看我是怎么做到的:

1- 我们不需要函数 showSelectedDay 所以我删除了它。

2- 我们不需要状态 const [activeItem, setActiveItem] = useState("");.

3- 添加新状态const [dayTrainings, setDayTrainings] = useState([]);

4- 将 handleItemClick 更新为:

  const [dayTrainings, setDayTrainings] = useState([]);
  const handleItemClick = (e) => {
    days.forEach((element, index) => {
      if (e.target.name === element.id) {
        console.log("selected day is " + element.date);
        setDayTrainings(element.dayTrainings);
      } else {
        console.log("not selected, day id is " + element.id);
      }
    });
  };

5- 在渲染中 return:

      {dayTrainings.length > 0 && (
        <ScheduledTrainingCard
          dayTraining={dayTrainings}
        ></ScheduledTrainingCard>
      )

ScheduledTrainingCard 示例:

export default function scheduledTrainingCard(props) {
  console.log(props.dayTraining);
  return (<>
      {
        props.dayTraining.map((item, index) => 
        <p key={index}>
          {item['time']}<br/>
          {item['training']}<br/>
          {item['trainer']}<br/>
          <br/><br/>
        </p>)
      }
    </>);
}

输出示例: output