【问题标题】:React context - undefined - json反应上下文 - 未定义 - json
【发布时间】:2021-11-01 22:38:02
【问题描述】:

我是 React 的初学者,面临一个未定义的问题。所以这里我有我的上下文文件,它带有从“data.json”文件中获取数据的 useEffect 函数。在 im 内部还返回一个带有键值对的新数组并使用该数组更新状态。因此,如果我想 console.log 一个状态,它会向我显示一个填充了我上面提到的键值对的数组。但是,当我想 console.log 例如数组(状态)的第一个索引时,例如“name”键它不知道什么是“name”。 有什么建议么?我附加了一个上下文文件和 data.json 文件。

import React from "react";
import { useState, useEffect } from "react";

export const Context = React.createContext({
  onChooseMoon: () => {},
  onChooseMars: () => {},
});

const ContextProvider = (props) => {
  const [planet, setPlanets] = useState();

  useEffect(() => {
    fetch("./data.json")
      .then((response) => {
        return response.json();
      })
      .then((data) => {
        const transformedData = data.destinations.map((destination) => {
          return {
            name: destination.name,
            img: destination.images.png,
            desc: destination.description,
            dist: destination.distance,
            travel: destination.travel,
          };
        });
        setPlanets(transformedData);
      });
  }, []);

  if (planet) {
    setPlanets(planet[0]);
    console.log("hello"); //shows hello 2 times but only in here (context file) //console.logs from component file does not show anything
  }

  const setMoonHandler = () => {
    setPlanets(planet[0]);

    // return {
    //   name: planet[0].name,
    //   img: planet[0].img,
    //   desc: planet[0].description,
    //   dist: planet[0].distance,
    //   travel: planet[0].travel,
    // };
  };

  const setMarsHandler = () => {
    setPlanets(planet[1]);

    // return {
    //   name: planet[1].name,
    //   img: planet[1].img,
    //   desc: planet[1].description,
    //   dist: planet[1].distance,
    //   travel: planet[1].travel,
    // };
  };

  return (
    <Context.Provider
      value={{
        planet: planet,
        onChooseMoon: setMoonHandler,
        onChooseMars: setMarsHandler,
      }}
    >
      {props.children}
    </Context.Provider>
  );
};

export default ContextProvider;

{
  "destinations": [
    {
      "name": "Moon",
      "images": {
        "png": "../assets/destination/image-moon.png",
        "webp": "./assets/destination/image-moon.webp"
      },
      "description": "See our planet as you’ve never seen it before. A perfect relaxing trip away to help regain perspective and come back refreshed. While you’re there, take in some history by visiting the Luna 2 and Apollo 11 landing sites.",
      "distance": "384,400 km",
      "travel": "3 days"
    },
    {
      "name": "Mars",
      "images": {
        "png": "./assets/destination/image-mars.png",
        "webp": "./assets/destination/image-mars.webp"
      },
      "description": "Don’t forget to pack your hiking boots. You’ll need them to tackle Olympus Mons, the tallest planetary mountain in our solar system. It’s two and a half times the size of Everest!",
      "distance": "225 mil. km",
      "travel": "9 months"
    },
    {
      "name": "Europa",
      "images": {
        "png": "./assets/destination/image-europa.png",
        "webp": "./assets/destination/image-europa.webp"
      },
      "description": "The smallest of the four Galilean moons orbiting Jupiter, Europa is a winter lover’s dream. With an icy surface, it’s perfect for a bit of ice skating, curling, hockey, or simple relaxation in your snug wintery cabin.",
      "distance": "628 mil. km",
      "travel": "3 years"
    },
    {
      "name": "Titan",
      "images": {
        "png": "./assets/destination/image-titan.png",
        "webp": "./assets/destination/image-titan.webp"
      },
      "description": "The only moon known to have a dense atmosphere other than Earth, Titan is a home away from home (just a few hundred degrees colder!). As a bonus, you get striking views of the Rings of Saturn.",
      "distance": "1.6 bil. km",
      "travel": "7 years"
    }
  ],
  "crew": [
    {
      "name": "Douglas Hurley",
      "images": {
        "png": "./assets/crew/image-douglas-hurley.png",
        "webp": "./assets/crew/image-douglas-hurley.webp"
      },
      "role": "Commander",
      "bio": "Douglas Gerald Hurley is an American engineer, former Marine Corps pilot and former NASA astronaut. He launched into space for the third time as commander of Crew Dragon Demo-2."
    },
    {
      "name": "Mark Shuttleworth",
      "images": {
        "png": "./assets/crew/image-mark-shuttleworth.png",
        "webp": "./assets/crew/image-mark-shuttleworth.webp"
      },
      "role": "Mission Specialist",
      "bio": "Mark Richard Shuttleworth is the founder and CEO of Canonical, the company behind the Linux-based Ubuntu operating system. Shuttleworth became the first South African to travel to space as a space tourist."
    },
    {
      "name": "Victor Glover",
      "images": {
        "png": "./assets/crew/image-victor-glover.png",
        "webp": "./assets/crew/image-victor-glover.webp"
      },
      "role": "Pilot",
      "bio": "Pilot on the first operational flight of the SpaceX Crew Dragon to the International Space Station. Glover is a commander in the U.S. Navy where he pilots an F/A-18.He was a crew member of Expedition 64, and served as a station systems flight engineer."
    },
    {
      "name": "Anousheh Ansari",
      "images": {
        "png": "./assets/crew/image-anousheh-ansari.png",
        "webp": "./assets/crew/image-anousheh-ansari.webp"
      },
      "role": "Flight Engineer",
      "bio": "Anousheh Ansari is an Iranian American engineer and co-founder of Prodea Systems. Ansari was the fourth self-funded space tourist, the first self-funded woman to fly to the ISS, and the first Iranian in space."
    }
  ],
  "technology": [
    {
      "name": "Launch vehicle",
      "images": {
        "portrait": "./assets/technology/image-launch-vehicle-portrait.jpg",
        "landscape": "./assets/technology/image-launch-vehicle-landscape.jpg"
      },
      "description": "A launch vehicle or carrier rocket is a rocket-propelled vehicle used to carry a payload from Earth's surface to space, usually to Earth orbit or beyond. Our WEB-X carrier rocket is the most powerful in operation. Standing 150 metres tall, it's quite an awe-inspiring sight on the launch pad!"
    },
    {
      "name": "Spaceport",
      "images": {
        "portrait": "./assets/technology/image-spaceport-portrait.jpg",
        "landscape": "./assets/technology/image-spaceport-landscape.jpg"
      },
      "description": "A spaceport or cosmodrome is a site for launching (or receiving) spacecraft, by analogy to the seaport for ships or airport for aircraft. Based in the famous Cape Canaveral, our spaceport is ideally situated to take advantage of the Earth’s rotation for launch."
    },
    {
      "name": "Space capsule",
      "images": {
        "portrait": "./assets/technology/image-space-capsule-portrait.jpg",
        "landscape": "./assets/technology/image-space-capsule-landscape.jpg"
      },
      "description": "A space capsule is an often-crewed spacecraft that uses a blunt-body reentry capsule to reenter the Earth's atmosphere without wings. Our capsule is where you'll spend your time during the flight. It includes a space gym, cinema, and plenty of other activities to keep you entertained."
    }
  ]
}

import Header from "../components/Header/Header";
import Planets from "../components/Planets/Planets";
import styles from "./Destination.module.css";
import ChoosePlanet from "../components/Planets/ChoosePlanet";
import { useContext } from "react";
import { Context } from "../store/context";

const Destination = () => {
  const ctx = useContext(Context);

  //does not show anything, which means planet is not true
  if (ctx.planet) {
    console.log(ctx.planet[0].name);
    console.log(ctx.planet);
    console.log("planet is true");
  }

  return (
    <div className={styles.body}>
      <Header />
      <h2>
        <span>01</span>PICK YOUR DESTINATION
      </h2>
      <main className={styles.main}>
        {ctx.planet && <Planets img={ctx.planet.img} alt="planet" />}
        {ctx.planet && (
          <ChoosePlanet
            name={ctx.planet.name}
            text={ctx.planet.desc}
            distance={ctx.planet.dist}
            time={ctx.planet.travel}
          />
        )}
      </main>
    </div>
  );
};

export default Destination;

【问题讨论】:

    标签: reactjs json


    【解决方案1】:

    useEffect 直到第一次渲染后才会运行,因此在第一次渲染时,您的 planet 变量仍然是您用于初始化它的值 (true)。

    请尝试以下方法:将planet 的初始值保留为undefined

    // no value is the same as `undefined` when invoking a function
    const [planet, setPlanets] = useState();
    

    然后,每当您在代码中使用 planet 时,请先检查以确保它不是 undefined,然后再尝试使用它/访问其属性:

    if (planet) {
      // planet is not `undefined`
      console.log(planet[0]); // ok
    }
    else {
      // planet is falsy, so do something else
    }
    

    【讨论】:

    • 谢谢!它奏效了。
    • 嘿,您的上述解决方案有效,但我放弃了在每个 setPlanetHandler 中为具体索引创建对象。我决定在它自己的设置函数中操纵状态(不知道它是否是一个好习惯),所以当点击正确的按钮时,它会改变状态的索引。但是现在“行星”状态在组件文件中不起作用。它不被认为是真正的价值。看起来它是虚假的,我不知道为什么。我在帖子中插入了更新的屏幕。可以看看吗?
    • 我建议您在有新问题时发布一个新问题,因为其他问题已经得到解答。
    猜你喜欢
    • 1970-01-01
    • 2019-05-24
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2023-03-11
    • 2019-12-25
    • 2021-01-10
    相关资源
    最近更新 更多