【问题标题】:React: Having trouble rendering nested json dataReact:渲染嵌套的 json 数据时遇到问题
【发布时间】:2019-12-31 03:26:57
【问题描述】:

我有一个嵌套的 json 在我的本地服务器中运行,我正在尝试通过能够输出这些嵌套数据来练习反应。对于这个,我试图只显示一天并输出白天可用的时间段。我正处于尝试输出每个“插槽”的阶段,并将使用按钮/切换来放置更多功能。

使用以下代码,我只能完成我认为获取“天”(星期一,星期二...)的内容。如果我错了,请纠正我,但我认为它们只被解析为字符串,而不是作为对象或数组维护,所以我没有注意到我可以获取“插槽”。另一个证据是,当我尝试映射“日”时,它正在映射字符串。

我认为我的问题是当它被传递到组件树时,我没有理解和丢失对 props 的跟踪。教程和指南解释了映射的一般意义,但我要么丢失了维护道具的特定细节,要么我在映射方面做错了。

另外,正如您可能知道的那样,这是我在互联网上的第一篇与代码相关的帖子。我还想询问您关于编码(或像宠物一样)的询问或提供有用信息的提示。我想更多地参与这些资源,以测试/练习我对其他人问题的了解。

当然,挑选任何更好的反应语法。我在这方面只有一周大,并试图尽可能多地吸收有关 react 的信息。

json

const advisor = [
    {
      id: 2,
      name: { first: "John", last: "Doe" },
      email: "jdoe@harvard.edu",
      availability: {
        monday: {
          slot: { start: 1400, end: 1410, available: true, student: null },
          slot: { start: 1415, end: 1425, available: true, student: null },
          slot: { start: 1430, end: 1440, available: false, student: null },
          slot: { start: 1445, end: 1455, availabie: true, student: null }
        },
        tuesday: {},
        wednesday: {},
        thurday: {
          // slot1: { start: 1400, end: 1410, available: true, student: null },
          // slot2: { start: 1415, end: 1425, available: true, student: null },
          // slot3: { start: 1430, end: 1440, available: true, student: null },
          // slot4: { start: 1445, end: 1455, availabie: true, student: null }
        },
        friday: {}
      }
    }
  ];

应用

import React from "react";
import Advisors from "./components/advisors/advisors.jsx";

function App() {
  return (
    <div className="App">
      <Advisors />
    </div>
  );
}

export default App;

顾问

import React, { Component } from "react";
import Availability from "./availability/availability.jsx";

class Advisors extends Component {
  constructor(props) {
    super(props);
    this.state = {
      advisors: []
    };
  }

  componentDidMount = () => {
    this.fetchData();
  };

  fetchData = () => {
    fetch("/api/advisors")
      .then(response => response.json())
      .then(
        advisors => this.setState({ advisors })
      )
      .catch(error => console.log("Parse Failed", error));
  };

  render() {
    const { advisors } = this.state;

    return (
      <div>
        {advisors.map(advisor => {

          return (
            <div key={advisor.id}>
              <h2>
                {advisor.name.first} {advisor.name.last}
              </h2>
              <h6>{advisor.email}</h6>
              {Object.keys(advisor.availability).map((day, key) => (
                //keys = {mon, tues, wed, thu, fri}
                <Availability key={key} day={day} />
              ))}
            </div>
          );
        })}
      </div>
    );
  }
}

export default Advisors;

可用性

import React, { Component } from "react";

class Availability extends Component {
  constructor(props) {
    super(props);
    this.state = {};
  }

  render() {
    const { day } = this.props;

    return (
      <div>
        <h4>{day}</h4>
        <ul>
          {Object.keys(day).map((x, i) => {
            return <li key={i}>{x.start}</li>;
          })}
        </ul>
      </div>
    );
  }
}

export default Availability;

【问题讨论】:

    标签: javascript arrays reactjs dictionary key


    【解决方案1】:

    您必须将availability 的键和值都传递给您的子&lt; Availability /&gt; 组件。

    首先,您应该确保来自 HTTP 请求的 availability 对象中的键是唯一的。目前,它们都具有相同的密钥,slot。可以考虑把名字改成slot1、slot2等。

    const advisor = [
        {
          id: 2,
          name: { first: "John", last: "Doe" },
          email: "jdoe@harvard.edu",
          availability: {
            monday: {
              slot1: { start: 1400, end: 1410, available: true, student: null },
              slot2: { start: 1415, end: 1425, available: true, student: null },
              slot3: { start: 1430, end: 1440, available: false, student: null },
              slot4: { start: 1445, end: 1455, availabie: true, student: null }
            },
            // others
          }
        }
      ];
    

    在您的父 Advisors 组件上,这是您需要更改的。如您所见,您需要将整个 availability 对象传递到您的子组件中,以便数据可用于渲染。

    {Object.keys(advisor.availability).map((day, key) => (
      <Availability key={key} day={day} availability={advisor.availability[day]}/>
    ))}
    

    在你的孩子Availability 组件上,

    您需要映射和渲染作为道具传递给它的可用性开始时间。

    <ul>
      {Object.keys(availability).map((x, i) => {
        return <li key={i}>{availability[x].start}</li>;
      })}
    </ul>
    

    我在这里创建了一个demo。

    【讨论】:

    • 哇,当它看起来像这样时,语法完全有意义。我忘记了在组件中传递可用性的可能性。当我从 Object.keys 使用 advisor.availability 时,我认为传递 advisor.availability 是非法的,但这显然是我一直试图传递的东西! 'day=' 'availability=' 还有一个术语吗?道具?孩子们?
    • 另外,如果您知道最后一个 json 层是 (start,end,available,student),您是否更愿意制作另一个分支可用性的新组件?还是将孩子全部呈现在可用性中?
    • 它们被称为道具!你可以在这里阅读更多关于它的信息reactjs.org/docs/components-and-props.html
    • 我认为在可用性中渲染它很好:) 你这样做的方式已经很好了
    【解决方案2】:

    问题在于您传递道具的方式。注意这一行

    Object.keys(advisor.availability).map((day, key) => (
       //keys = {mon, tues, wed, thu, fri}
       <Availability key={key} day={day} />
    ))
    

    Object.keys(advisor.availability) 返回数组 [mon, tues, wed, thu, fri]。现在,在 arr.map((day,key)=&gt;{}) 中,day 将值 mon,tues,wed,etc. 一个接一个地获取,它是一个字符串,您将其作为道具传递给 &lt;Availability/&gt;

    为了传递值对象,应该是

    Object.keys(advisor.availability).map((day, key) => (
       <Availability key={key} day={advisor.availability[day]} />
    ))
    

    现在,您的 advisor 对象中存在另一个问题。注意monday 键入您的对象。它多次使用相同的键 slot,这在 JS 对象中是不允许的,因此 JS 将用最后一个插槽替换它,最终您只有 1 个插槽。

    monday: {
      slot: { start: 1400, end: 1410, available: true, student: null },
      slot: { start: 1415, end: 1425, available: true, student: null },
      slot: { start: 1430, end: 1440, available: false, student: null },
      slot: { start: 1445, end: 1455, availabie: true, student: null }
    }
    

    您可以通过两种方式修复它(也许更多)。

    1. 将键更改为 slot1、slot2 等。例如,
    monday: {
      slot1: { start: 1400, end: 1410, available: true, student: null },
      slot2: { start: 1415, end: 1425, available: true, student: null },
      slot3: { start: 1430, end: 1440, available: false, student: null },
      slot4: { start: 1445, end: 1455, availabie: true, student: null }
    }
    

    在Availability.js 中,替换此代码

    {Object.keys(day).map((x, i) => {
      return <li key={i}>{x.start}</li>;
    })}
    

    有了这个

    {Object.keys(day).map((x, i) => {
      return <li key={i}>{day[x].start}</li>;
    })}
    
    1. 另一种方法是将其定义为数组。例如。
    monday: [
      { start: 1400, end: 1410, available: true, student: null },
      { start: 1415, end: 1425, available: true, student: null },
      { start: 1430, end: 1440, available: false, student: null },
      { start: 1445, end: 1455, availabie: true, student: null }
    ]
    

    在Availability.js 中,替换此代码

    {Object.keys(day).map((x, i) => {
      return <li key={i}>{x.start}</li>;
    })}
    

    有了这个

    {day.map((x, i) => {
      return <li key={i}>{x.start}</li>;
    })}
    

    【讨论】:

    • 通过更新传递道具的方式,我尝试了您的第一个解决方案,但在尝试传递 [x].start 时出错,说它是一个带键的对象,需要呈现为数组.我认为这是因为 x 是嵌套 json 的下一层(开始,结束,可用,学生),我必须映射 day[x]?第二种解决方案看起来非常干净,并且摆脱了插槽冗余。这是我遇到的一个难题,因为我打算让插槽数量可变,所以我可能会在这个项目中使用它。
    • 另外,如果您知道最后一个 json 层是 (start,end,available,student),您是否更愿意制作另一个分支可用性的新组件?还是将孩子全部呈现在可用性中?
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-03-02
    • 2015-10-07
    • 1970-01-01
    • 1970-01-01
    • 2020-09-24
    • 1970-01-01
    相关资源
    最近更新 更多