简体   繁体   English

反应上下文 - 状态不正确

[英]React context - state not true

Im making a project and got stucked at context file.我正在制作一个项目并被困在上下文文件中。 I want my state planet to be true so i can use it in my component file.我希望我的状态planet是真实的,这样我就可以在我的组件文件中使用它。 At the start it becomes true showing the right index of the array but in the end its becoming undefined.一开始它会显示数组的正确索引,但最后它变得未定义。 Can someone point me out what is causing "planet" state to be undefined at the end?有人能指出我最终导致“行星”状态未定义的原因吗? Im talking about if statement - if (planet) {...} .我在谈论 if 语句 - if (planet) {...} Im attaching code from context file and screen of my browser console.我从我的浏览器控制台的上下文文件和屏幕中附加了代码。 Would be nice if someone also told me if i can change state in its own setting function eg setPlanets(planet[0]) .如果有人还告诉我我是否可以在其自己的设置函数中更改状态,例如setPlanets(planet[0])

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(planet[0]);
    console.log("hello");
  }

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

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

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

export default ContextProvider;

在此处输入图片说明

Here's a breakdown of what's going on:以下是正在发生的事情的细分:

  1. Component mounts, value of planet is undefined , useEffect is triggered.组件挂载, planetundefineduseEffect被触发。 When useEffect runs setPlanets(transformedData) rerender is triggered.useEffect运行setPlanets(transformedData)会触发重新渲染。
  2. Value of planet is now whatever transformedData was (I'm assuming an array of planet objects). planet值现在是任何被transformedData (我假设是一个行星对象数组)。 Since planet is truthy, setPlanets(planet[0]) runs, causing a rerender.由于planet是真实的, setPlanets(planet[0])运行,导致重新渲染。
  3. Value of planet is now whatever transformedData[0] was (a single planet). planet值现在是任何transformedData[0] (单个行星)。 Since planet is still truthy, setPlanets(planet[0]) runs again, causing a rerender.由于planet仍然是真实的, setPlanets(planet[0])再次运行,导致重新渲染。
  4. Value of planet is now whatever transformedData[0][0] was. planet价值现在是任何transformedData[0][0] Since transformedData[0] was not an array and probably doesn't have the key 0 , the value of planet is now undefined again.由于transformedData[0]不是数组并且可能没有键0 ,因此现在再次undefined planet的值。

The issue is that if ever planet becomes defined, running setPlanet(planet[0]) will run until the value of planet becomes undefined again.问题是,如果planet被定义,运行setPlanet(planet[0])将一直运行,直到planet的值再次变为undefined

I think what you meant to do (judging by the naming) was to have two separate state variables.我认为你想要做的(从命名来看)是有两个单独的状态变量。 One to hold all of the planets, and one to hold a single (active/focused) planet.一个容纳所有行星,一个容纳单个(主动/聚焦)行星。

Here's an example:下面是一个例子:

const ContextProvider = (props) => {
  const [activePlanet, setActivePlanet] = useState();
  const [planets, setPlanets] = useState([]);

  useEffect(() => {
    fetch("./data.json") // same as before
  }, []);

  useEffect(() => {
    if (!activePlanet && planets.length > 0) {
        setActivePlanet(planets[0]);
        console.log(planets[0]);
        console.log("hello");
    }
  }, [activePlanet, planets]);

  // ...
};

Also it's generally a good idea to wrap all state updating logic in hooks (or tied to events like clicks), so I've added a useEffect to wrap the setActivePlanet call.此外,将所有状态更新逻辑包装在钩子中(或绑定到点击等事件)通常是一个好主意,所以我添加了一个useEffect来包装setActivePlanet调用。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM