如何解决反应:通过按钮onclick传递映射数据以显示在另一个组件上 1将共享的声明转移给共同的祖先 2使用上下文API 3使用状态管理库首选
我在传递从API映射的数据时遇到了一些困难,它会根据API数组中的事件数显示一堆事件卡。
这是我的活动卡组件;
export default function EventCard() {
const classes = useStyles();
const [data,setData] = useState([]);
useEffect(() => {
const fetchData = async () => {
const result = await axios("http://localhost:23455/Event");
setData(result.data);
};
fetchData();
},[]);
const handleClick = (value) => () => {
console.log(value);
};
return (
<div>
<Row>
{" "}
{data.map((item) => (
<Card
className={classes.root}
style={{ marginRight: "25px",marginBottom: "25px" }}
>
<CardHeader
avatar={
<Avatar aria-label="recipe" className={classes.avatar}>
{item.icon}
</Avatar>
}
action={
<IconButton aria-label="settings">
<MoreVertIcon />
</IconButton>
}
title={item.name}
subheader="September 14,2016"
/>
<CardMedia
className={classes.media}
image={LordsLogo}
title="Paella dish"
/>
<CardContent>
<Typography variant="body2" color="textSecondary" component="p">
<p key={item.id}> {item.description}</p>
<p key={item.id}> {item.startDate}</p>
<p key={item.id}> {item.endDate}</p>
</Typography>
</CardContent>
<CardActions disableSpacing>
<IconButton aria-label="add to favorites">
<Button variant="outlined">Steward</Button>
</IconButton>
<IconButton aria-label="share">
<Button variant="outlined" onClick={handleClick({ item })}>
Tickets
</Button>
</IconButton>
</CardActions>
</Card>
))}
</Row>
</div>
);
}
我有一个onclick函数,该函数记录将什么数据添加到“值” onclick中,如果单击卡,控制台将记录该特定卡的值:
我现在想要做的是在另一个称为ServiceForm的组件中使用此信息。我希望能够单击按钮,链接到ServiceForm,并使用ServiceForm组件中“项目”中的变量,理想情况如下所示;
<Form.Group as={Col} controlId="formGridForeName">
<Form.Label>**{item.description}**</Form.Label>
<Form.Control
name="firstName"
placeholder="Enter name"
onChange={this.handleChange}
/>
</Form.Group>
EventCard,如果functionalComponent和ServiceForm是基于类的组件,如何将信息从第一个传递给后者?谢谢
编辑:显示组件层次结构
ServiceForm在ServiceApplication中呈现,如下所示:
import * as React from "react";
import { ServiceForm } from "../components/ServiceForm";
class ServiceApplication extends React.Component {
render() {
return (
<React.Fragment>
<h1>Service Application</h1>
<h6>Users can use this page to apply for tickets.</h6>
<ServiceForm />
</React.Fragment>
);
}
}
export default ServiceApplication;
EventCard组件在EventsPage中呈现,如下所示;
import EventCard from "../components/EventCards/EventCard";
class EventsPage extends React.Component {
render() {
return (
<React.Fragment>
<h1>Events</h1>
<h6>
Welcome to the Events,here you can apply for seats or tickets at the
events shown below.
</h6>
<Row>
<EventCard />
</Row>
</React.Fragment>
);
}
}
export default EventsPage;
这个想法是在单击EventCard上的“ Tickets”按钮时传递ID(ID是从API中提取并映射的)。
解决方法
这是一个关于您如何真正在应用中存储状态的问题。
举一个简单的例子,其中一个组件是另一个组件的子组件。在这种情况下,父母可以将状态存储在本地,例如useState()并将其作为道具传递给孩子。
const SomeParent = () => {
const [isTrue,setIsTrue] = React.useState(true)
return (
<Child isTrue={isTrue} />
)
}
在某些情况下,您可能希望在多个组件或整个应用程序之间共享状态。在这种情况下,您会有很多不同的选择。
1。将状态提升到所需的最高点。
最简单的方法是将您在多个组件之间共享的状态移动到两个组件共享的最高点。 例如
Section component <- store state here
Parent one
child one
child two
Parent two
child one
在这里您可以再次使用useState()或将状态存储在useReducer()中,并向下传递调度。
数据流将如下所示:
-
段组件中的
- 初始化状态,例如const [someState,setSomeState]
- 将setSomeState回调向下传递到Parent组件,然后将子组件作为道具,例如
- 在子组件设置状态下,使用回调的onClick例如onClick = {()=> action(item)}
- 将状态值向下传递到您的第二个“父”组件,然后将其子组件,例如
- 您可以通过表格访问状态
这可以是一个对象或多个状态值。随着复杂性的增加,我倾向于使用useReducer()。
2。在您的应用程序中实现useContext OR Redux ,以创建可从任何组件访问的应用程序状态(这是一个更大的解释,每个组件上都有很多资源...
注意::我不确定您为什么在这里使用两组括号:
const handleClick = (value) => () => {
console.log(value);
};
,并且在调用handleClick时,如果要传递值,则需要将其切换为箭头功能:
onClick={handleClick({ item })
...
onClick={() => handleClick(item)}
,
基本上,您希望通过传递项目prop从功能组件中触发类组件函数,如果它是父子组件,则可以将函数作为prop传递,并在需要时从父组件或子组件中触发它。
但是在您的两个组件都没有连接的情况下,不使用redux可以做的是创建一个公共本地存储,例如将其称为localStorage.js:
var PublicData = (function() {
var data = null;
var getData = function() {
return data;
};
var setData = function(props) {
data = props;
};
var clearData = function() {
data = null;
};
return {
GET: getData,SET: setData,CLEAR: clearData
}
})();
export default PublicData;
然后您将其导入并按以下方式使用:
import PublicData from './PublicData.js';
PublicData.SET(apiData); // you set your data once you fetch it
const data = PublicData.GET(); // get data
PublicData.CLEAR(); // clear your data
注意:这不是实际的localStorage,但它的工作原理相同,它将帮助您在组件之间共享变量。
,尝试一下:
const handleClick = (value) => {
console.log(value);
};
<Button variant="outlined" onClick={() => handleClick({ item })} />
,
Parent
/ \
Service Event
我从您的问题中猜测,您的应用程序树的简化看起来像上面的那样。
您遇到的问题如下:
Parent
/ \
Service Event
Data
在自上而下的体系结构中,Service不了解事件以及该分支中那里的任何数据。
因此,您有2个选项(可能更多,但是这2个选项可以使您受益匪浅):
- 提升数据
Parent
Data
/ \
Service Event
- 将数据存储在其他位置并提供访问机制
Data
Parent
/ \
Service Event
选项1 可以通过传递道具(数据)和函数(使用道具传递)来实现,以操纵数据(或实际上首先填充即获取数据)>
流程看起来像: 父母是有状态的。父级将数据的当前状态传递给关心它的子级(在您的情况下,看起来像服务和事件)。父级将一个函数传递给Event,该函数可以附加到元素的Event子树中的点击处理程序。
由于向下传递函数,因此在调用该单击处理程序时,它可以设置Parent的状态,正常的自上而下的渲染流程将从该状态处理父级的设置更新,并将数据更改沿树向下传递,从而它们将(通常)调用重新渲染。
我认为Recoil使用这种方法,并且在我们希望拆分应用程序并避免使用全局状态管理时,它再次变得越来越流行。
选项2 是Redux,Cerebral,MobX等数据管理库的所在地。如果您熟悉发布者/订阅者模式,则将了解它们的工作原理。
本质上,这些库为您的应用程序保留共享状态,例如您在此处拥有的数据。然后,它们(通常)为您提供一种模式(通过已发布的事件)来管理状态的更改,并确保订阅该数据的组件接收到新的状态并进行更新。
此处的“讨论”与选择1不同: 点击处理程序会发布一个事件,从本质上讲,该事件要求对数据进行某种处理。操作发生(或不发生),并且订阅者被更新。在您的情况下,单击将告知集中存储(即正在侦听的任何内容)以获取数据,完成后将数据更改(从空到填充),它将允许所有相关元素(或者很有可能是整个应用程序树并利用自上而下的呈现方式)对此有所了解,他们可以做他们需要做的事情。
您选择哪种选择完全取决于您,它们都有优点和缺点。
祝您好运,请仔细考虑您的数据,如何存储数据以及如何使用它!
,很高兴您提出这个问题,因为这是很多次已经解决的问题。其他撰稿人写了不错的全面答案,所以我将其简短。
1。将共享的声明转移给共同的祖先。
这很简单,但是很快就变得很毛茸茸。
2。使用上下文API
您可以使用react的上下文API将负责获取数据的代码移动到上下文中,并在应用程序中的任何位置使用该数据,而不会带来很多麻烦。如今,这种方法越来越受欢迎。 Take a look at this和here's a sweet library to help you get started。
3。使用状态管理库(首选)
您可以选择使用任何您喜欢的状态管理库来解决此问题。有很多选择,redux
是最受欢迎的选择,并且有充分的理由。它使您能够实现数据和UI之间的关注分离,但是有点冗长。
Mobx
也很受欢迎,并且具有良好的开发人员经验,但是我个人不喜欢它对您的代码强制采用某种样式。
如果您是新来的反应者和状态管理者,那么这些库可能确实令人生畏。我建议您从zustand开始。它非常简单,可以完成工作。 ;)
,您可以简单地使用Custom Event
https://developer.mozilla.org/en-US/docs/Web/API/CustomEvent/CustomEvent。这不是最佳实践,但可以。在EventCard
中,当用户单击您时,调度一个自定义事件,其有效负载为item
,则ServiceForm
将侦听该事件并存储{{1} }作为状态。在这里工作演示
https://codesandbox.io/s/distracted-aryabhata-ec6gc
EventCard
item
服务表格
const handleClick = () => {
const item = {
description: "This is description"
};
const event = new CustomEvent("customEvent",{
detail: item
});
window.dispatchEvent(event);
};
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。