【问题标题】:Why does updating state from fetch result updates the whole array of objects while rendering?为什么从获取结果更新状态会在渲染时更新整个对象数组?
【发布时间】:2022-01-04 22:25:50
【问题描述】:

我遇到了问题,我想根据锻炼对象数组中包含的坐标获取城市名称。这是Filesprojectsandbox的链接

    export const WorkoutsData = [
  {
  id: 1,
  coords: {latitude: 56.27360151291927, 
  longitude:-82.84886256490017},
  },
  
  {
  id: 2,
  coords: {latitude: 49.27360151291927, 
  longitude: -75.84886256490017},
  },

  {
  id: 3,
  coords: {latitude: 39.27360151291927, 
  longitude: -79.84886256490017},
  }
];



import React, { useEffect, useState } from "react";
import "./styles.css";
import { WorkoutsData } from "./WorkoutLocation";

const App = () => {
  const [workouts, setWorkouts] = useState(WorkoutsData);
  const [cityName, setCityName] = useState([]);

  const id = (Date.now() + "").slice(-10);

  useEffect(() => {
    workouts.map((workout) => {
      fetch(
        `https://geocode.xyz/${workout.coords.latitude},${workout.coords.longitude}?geoit=json`
      )
        .then((res) => res.json())
        .then((result) => {
          setCityName([`${result.staddress}, ${result.city}`]);
        });
    });
  }, [workouts]);

  return (
    <>
      <div key={id}>
        {workouts.map((workout) => {
          return <h2 key={workout.id}>{`${cityName}`}</h2>;
        })}
      </div>
    </>
  );
};

export default App;

我对代码进行了一些编辑并设法获得了唯一的位置名称,但这次我不会获得第一个锻炼对象的位置名称。然后位置名称将传递给第二个对象。

【问题讨论】:

  • 在获取每次锻炼的位置时,您会不断覆盖 cityName。也许您可以构建一个城市名称数组,然后在状态中存储和读取它。
  • 我将 setCityName(${result.staddress}, ${result.city}) 更新为 setCityName(res => [...res, ${result.staddress}, ${result.city}]) 并将我的 usestate 更新为 const [cityname, setCityName] = useState([]);如何映射 cityname 数组并为每个对象显示 cityname?
  • 当我控制台 .log(cityName) 我得到相同的 cityName 两次
  • 您的cityName 变量只包含一个字符串。您每次都覆盖相同的字符串。如果要保存字符串列表,请使用列表。
  • 我将 setCityName(${result.staddress}, ${result.city}) 更新为 setCityName(res => [...res, [${result.staddress}, ${result. city]}])当我渲染时,我在一个锻炼容器中获得所有位置名称

标签: reactjs dictionary fetch use-state reverse-geocoding


【解决方案1】:

您应该更清楚您提供的代码。您省略了部分代码,这将使您的组件的结构更加清晰。

您似乎以错误的方式解决问题。

  • 首先,如果您想呈现锻炼地点列表,您的状态应该包含一个列表而不是单个字符串。
    const [cityName, setCityName] = useState(null)

    workouts.map((exercise) => {
        ...
        setCityName(`${result.staddress}, ${result.city}`)
        ...
    }

每次查找另一个位置时,上面的内容只是将“cityName”设置为一个字符串。它应该包含一个字符串列表。

  • 接下来,你的锻炼可能应该作为道具传递给组件(从你提供的几个代码 sn-ps 中不确定)。

  • 然后最后 - 当你渲染结果时 - 你从“锻炼”状态经历所有锻炼,并渲染一些甚至不在“锻炼”状态的东西:你渲染“cityName”状态,它现在保存您查找的最后一次锻炼的位置:

return (
        <>
            workouts.map((workout) => {
                <h2 className = "workout-title">{cityName}</h2>
            }
        </>
    )

以下可能是解决您的问题的更好方法(不确定,因为我无法从您显示的有限代码中确定这是否正是您想要做的):

WorkoutLocations.js:

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

export const WorkoutLocations = ({ workoutsList }) => {
    const [cities, setCities] = useState([]);

    useEffect(() => {
        const getLocation = async (workout) =>
                fetch(`https://geocode.xyz/${workout.coords.latitude},${workout.coords.longitude}?geoit=json`)
            .then((res) => res.json())
            .then((res) => `${res.staddress}, ${res.city}`);                    
        const getLocations = async () =>
            Promise.all(workoutsList.map((workout) => getLocation(workout)));        
        getLocations().then((res) => setCities(res));
    }, [workoutsList]);

    return (
        <>
            {cities &&
                cities.map((city, id) => (
                    <h2 key={id} className="workout-title">
                        {city}
                    </h2>
                ))}
        </>
    );
};

(在您的应用内):

import { WorkoutLocations } from "./WorkoutLocations"

...

const workouts = [
    {
        coords: {
            latitude: 41.27360151291927,
            longitude: -72.84886256490017
        }
    },
    {
        coords: {
            latitude: 40.7128,
            longitude: -74.006
        }
    }
];

...

return (
    <WorkoutLocations
        workoutsList={workouts}
    />
)

你可以在CodeSandbox看到工作代码。

【讨论】:

  • 谢谢鲁本!我试过你的代码,但它会返回未定义。我对代码做了一些修改。你可以看看它并给我任何建议。
  • 您尝试过 CodeSandbox 链接吗?代码在那里工作。
  • 如果您不包含整个代码,我很难再提供任何建议。我看不到整个组件结构。您正在调用 useState 挂钩,但不是从函数内部调用。当您不显示完整代码时,我看不出出了什么问题。
  • 另外,当您编辑代码时,您应该在您发布的初始问题下添加新代码,而不仅仅是更改整个问题。否则,从没有看到您最初问题的新访问者的角度来看,我的回答将变得完全无关紧要。
  • 这是我第一次发布问题,所以我不知道规则和程序。这也是我所有的代码github.com/kashcodernyc/react-mapty/tree/master/src
猜你喜欢
  • 2020-11-04
  • 1970-01-01
  • 1970-01-01
  • 2020-08-14
  • 1970-01-01
  • 2020-08-12
  • 1970-01-01
  • 2019-09-27
  • 2020-09-05
相关资源
最近更新 更多