传递给子组件时道具未定义(反应挂钩)
Props is undefined when passed to a child component (react hooks)
我正在构建一个简单的议程组件,运行 成为一个问题。这个想法是,当一个人点击这一天,然后看到这一天的培训。我的逻辑如下
- 单击按钮时我将状态设置为日期 id
- 在现有活动项上,三元运算符呈现组件
- 我将函数调用作为 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([]);
然后根据用户的选择为 setSelectedDays
和 activeItem
设置值:
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
我正在构建一个简单的议程组件,运行 成为一个问题。这个想法是,当一个人点击这一天,然后看到这一天的培训。我的逻辑如下
- 单击按钮时我将状态设置为日期 id
- 在现有活动项上,三元运算符呈现组件
- 我将函数调用作为 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([]);
然后根据用户的选择为 setSelectedDays
和 activeItem
设置值:
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