反应:通过按钮onclick传递映射数据以显示在另一个组件上 1将共享的声明转移给共同的祖先 2使用上下文API 3使用状态管理库首选

如何解决反应:通过按钮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中,如果单击卡,控制台将记录该特定卡的值:

enter image description here

我现在想要做的是在另一个称为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>
      &nbsp; &nbsp;
      <h1>Service Application</h1>
      &nbsp; &nbsp;
      <h6>Users can use this page to apply for tickets.</h6>
      &nbsp; &nbsp;
      <ServiceForm />
    </React.Fragment>
  );
 }
}

export default ServiceApplication;

EventCard组件在EventsPage中呈现,如下所示;

import EventCard from "../components/EventCards/EventCard";

class EventsPage extends React.Component {
  render() {
    return (
      <React.Fragment>
        &nbsp; &nbsp;
        <h1>Events</h1>
        &nbsp; &nbsp;
        <h6>
          Welcome to the Events,here you can apply for seats or tickets at the
      events shown below.
        </h6>
        &nbsp; &nbsp;
        <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()中,并向下传递调度。

数据流将如下所示:

    段组件中的
  1. 初始化状态,例如const [someState,setSomeState]
  2. 将setSomeState回调向下传递到Parent组件,然后将子组件作为道具,例如
  3. 在子组件设置状态下,使用回调的onClick例如onClick = {()=> action(item)}
  4. 将状态值向下传递到您的第二个“父”组件,然后将其子组件,例如
  5. 您可以通过表格访问状态

这可以是一个对象或多个状态值。随着复杂性的增加,我倾向于使用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个选项可以使您受益匪浅):

  1. 提升数据
    Parent
     Data
   /      \
Service  Event
  1. 将数据存储在其他位置并提供访问机制
Data

    Parent
   /      \
Service  Event

选项1 可以通过传递道具(数据)和函数(使用道具传递)来实现,以操纵数据(或实际上首先填充即获取数据)>

流程看起来像: 父母是有状态的。父级将数据的当前状态传递给关心它的子级(在您的情况下,看起来像服务和事件)。父级将一个函数传递给Event,该函数可以附加到元素的Event子树中的点击处理程序。

由于向下传递函数,因此在调用该单击处理程序时,它可以设置Parent的状态,正常的自上而下的渲染流程将从该状态处理父级的设置更新,并将数据更改沿树向下传递,从而它们将(通常)调用重新渲染。

我认为Recoil使用这种方法,并且在我们希望拆分应用程序并避免使用全局状态管理时,它再次变得越来越流行。

选项2 ReduxCerebralMobX等数据管理库的所在地。如果您熟悉发布者/订阅者模式,则将了解它们的工作原理。

本质上,这些库为您的应用程序保留共享状态,例如您在此处拥有的数据。然后,它们(通常)为您提供一种模式(通过已发布的事件)来管理状态的更改,并确保订阅该数据的组件接收到新的状态并进行更新。

此处的“讨论”与选择1不同: 点击处理程序会发布一个事件,从本质上讲,该事件要求对数据进行某种处理。操作发生(或不发生),并且订阅者被更新。在您的情况下,单击将告知集中存储(即正在侦听的任何内容)以获取数据,完成后将数据更改(从空到填充),它将允许所有相关元素(或者很有可能是整个应用程序树并利用自上而下的呈现方式)对此有所了解,他们可以做他们需要做的事情。

您选择哪种选择完全取决于您,它们都有优点和缺点。

祝您好运,请仔细考虑您的数据,如何存储数据以及如何使用它!

,

很高兴您提出这个问题,因为这是很多次已经解决的问题。其他撰稿人写了不错的全面答案,所以我将其简短。

1。将共享的声明转移给共同的祖先。

这很简单,但是很快就变得很毛茸茸。

2。使用上下文API

您可以使用react的上下文API将负责获取数据的代码移动到上下文中,并在应用程序中的任何位置使用该数据,而不会带来很多麻烦。如今,这种方法越来越受欢迎。 Take a look at thishere'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 举报,一经查实,本站将立刻删除。

相关推荐


依赖报错 idea导入项目后依赖报错,解决方案:https://blog.csdn.net/weixin_42420249/article/details/81191861 依赖版本报错:更换其他版本 无法下载依赖可参考:https://blog.csdn.net/weixin_42628809/a
错误1:代码生成器依赖和mybatis依赖冲突 启动项目时报错如下 2021-12-03 13:33:33.927 ERROR 7228 [ main] o.s.b.d.LoggingFailureAnalysisReporter : *************************** APPL
错误1:gradle项目控制台输出为乱码 # 解决方案:https://blog.csdn.net/weixin_43501566/article/details/112482302 # 在gradle-wrapper.properties 添加以下内容 org.gradle.jvmargs=-Df
错误还原:在查询的过程中,传入的workType为0时,该条件不起作用 &lt;select id=&quot;xxx&quot;&gt; SELECT di.id, di.name, di.work_type, di.updated... &lt;where&gt; &lt;if test=&qu
报错如下,gcc版本太低 ^ server.c:5346:31: 错误:‘struct redisServer’没有名为‘server_cpulist’的成员 redisSetCpuAffinity(server.server_cpulist); ^ server.c: 在函数‘hasActiveC
解决方案1 1、改项目中.idea/workspace.xml配置文件,增加dynamic.classpath参数 2、搜索PropertiesComponent,添加如下 &lt;property name=&quot;dynamic.classpath&quot; value=&quot;tru
删除根组件app.vue中的默认代码后报错:Module Error (from ./node_modules/eslint-loader/index.js): 解决方案:关闭ESlint代码检测,在项目根目录创建vue.config.js,在文件中添加 module.exports = { lin
查看spark默认的python版本 [root@master day27]# pyspark /home/software/spark-2.3.4-bin-hadoop2.7/conf/spark-env.sh: line 2: /usr/local/hadoop/bin/hadoop: No s
使用本地python环境可以成功执行 import pandas as pd import matplotlib.pyplot as plt # 设置字体 plt.rcParams[&#39;font.sans-serif&#39;] = [&#39;SimHei&#39;] # 能正确显示负号 p
错误1:Request method ‘DELETE‘ not supported 错误还原:controller层有一个接口,访问该接口时报错:Request method ‘DELETE‘ not supported 错误原因:没有接收到前端传入的参数,修改为如下 参考 错误2:cannot r
错误1:启动docker镜像时报错:Error response from daemon: driver failed programming external connectivity on endpoint quirky_allen 解决方法:重启docker -&gt; systemctl r
错误1:private field ‘xxx‘ is never assigned 按Altʾnter快捷键,选择第2项 参考:https://blog.csdn.net/shi_hong_fei_hei/article/details/88814070 错误2:启动时报错,不能找到主启动类 #
报错如下,通过源不能下载,最后警告pip需升级版本 Requirement already satisfied: pip in c:\users\ychen\appdata\local\programs\python\python310\lib\site-packages (22.0.4) Coll
错误1:maven打包报错 错误还原:使用maven打包项目时报错如下 [ERROR] Failed to execute goal org.apache.maven.plugins:maven-resources-plugin:3.2.0:resources (default-resources)
错误1:服务调用时报错 服务消费者模块assess通过openFeign调用服务提供者模块hires 如下为服务提供者模块hires的控制层接口 @RestController @RequestMapping(&quot;/hires&quot;) public class FeignControl
错误1:运行项目后报如下错误 解决方案 报错2:Failed to execute goal org.apache.maven.plugins:maven-compiler-plugin:3.8.1:compile (default-compile) on project sb 解决方案:在pom.
参考 错误原因 过滤器或拦截器在生效时,redisTemplate还没有注入 解决方案:在注入容器时就生效 @Component //项目运行时就注入Spring容器 public class RedisBean { @Resource private RedisTemplate&lt;String
使用vite构建项目报错 C:\Users\ychen\work&gt;npm init @vitejs/app @vitejs/create-app is deprecated, use npm init vite instead C:\Users\ychen\AppData\Local\npm-