Маркеры React Leaflet не отображаются с данными о местоположении, полученными из API с использованием useEffect

Я пытаюсь визуализировать маркеры листовок с помощью React Leaflet с данными, полученными из API с использованием useEffect. Маркеры не отображаются, несмотря на то, что данные о местоположении на момент объявления маркера были ненулевыми (предположительно, из-за использования условного рендеринга, хотя я уже не так уверен).

Код для useEffect:

const [arr, setArr] = React.useState([]);
const [dataLoaded, setDataLoaded] = React.useState(false);

useEffect(() => {
    axios.get('http://localhost:8000/get-data/')
    .then(res => {
        if (res.data) {
          const data = res.data
          for (let i = 0; i < data.length; i++) {
            arr.push(data[i])
          }
        }
    })
    .then(res => {
      if ( arr.length > 0) {
        setDataLoaded(true)
      }
    })
}, [])

Код для рендеринга маркеров:

{ dataLoaded ? console.info(arr[0].latitude, arr[0].longitude) : null}
{ dataLoaded ? <Marker position = {[parseFloat(arr[0].latitude), parseFloat(arr[0].longitude)]}> 
    <Popup>
        A pretty CSS3 popup. <br /> Easily customizable.
    </Popup>
</Marker> : <></> }

Это пример того, как я пытаюсь визуализировать первый набор координат из моего массива данных. Я включил журналы консоли для отладки, которые выводят значения 36,77 и -199,41 для широты и долготы соответственно. Это те же переменные, которые используются для определения положения маркера. Однако по какой-то причине маркер не отображается на моей карте. Если я введу значения [36,77, -119,41] непосредственно в его позицию, маркер появится. Есть идеи, почему это происходит?

Редактировать: здесь скриншот моего массива данных после заполнения.

Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Улучшение производительности загрузки с помощью Google Tag Manager и атрибута Defer
Улучшение производительности загрузки с помощью Google Tag Manager и атрибута Defer
В настоящее время производительность загрузки веб-сайта имеет решающее значение не только для удобства пользователей, но и для ранжирования в...
Безумие обратных вызовов в javascript [JS]
Безумие обратных вызовов в javascript [JS]
Здравствуйте! Юный падаван 🚀. Присоединяйся ко мне, чтобы разобраться в одной из самых запутанных концепций, когда вы начинаете изучать мир...
Система управления парковками с использованием HTML, CSS и JavaScript
Система управления парковками с использованием HTML, CSS и JavaScript
Веб-сайт по управлению парковками был создан с использованием HTML, CSS и JavaScript. Это простой сайт, ничего вычурного. Основная цель -...
JavaScript Вопросы с множественным выбором и ответы
JavaScript Вопросы с множественным выбором и ответы
Если вы ищете платформу, которая предоставляет вам бесплатный тест JavaScript MCQ (Multiple Choice Questions With Answers) для оценки ваших знаний,...
1
0
196
2
Перейти к ответу Данный вопрос помечен как решенный

Ответы 2

Во-первых, обновление state типа arr должно находиться внутри setArr, также вам необходимо изменить ссылку array, использование push для обновления arr не приведет к повторной визуализации компонента.

Сначала useEffect с пустой зависимостью вы устанавливаете значение arr.

useEffect(() => {
    axios.get('http://localhost:8000/get-data/')
    .then(res => {
        if (res.data) {
            setArr(prevArr => [...prevArr, ...res.data]);
        }
    })
}, []);

Затем другой useEffect с зависимостью arr, чтобы установить dataLoaded

useEffect(() => {
    if (arr.length > 0) {
        setDataLoaded(true);
    }
}, [arr]);
Ответ принят как подходящий

Я бы изменил ваш код на что-то вроде этого

const [arr, setArr] = React.useState([]);
const [dataLoaded, setDataLoaded] = React.useState(false);
useEffect(() => {
    axios.get('http://localhost:8000/get-data/')
    .then(res => {
        if (res.data) {
          const data = res.data
          const items = []
          data.forEach(item => items.push(item))
          setArr(items)
        }
    })
    .then(res => {
      //here remove the condition arr.length > 0
      //instead you should have conditional rendering in your app
      //so if the data is loaded display <>No Items Found</> or something
      setDataLoaded(true)
    })
}, [])

причина, по которой вы хотите удалить условный setDataLoaded(true), заключается в том, что если вы извлекаете и выборка возвращает [], то ваш dataLoaded имеет значение false, даже если на самом деле загрузка завершена. Вы также уверены, что получаете данные? например, если вы добавите console.info(data) в свою выборку, вы увидите, что она загружается?

Существует также хакерский способ принудительного повторного рендеринга, выполнив что-то вроде этого

const [isRerender, setIsRerender] = React.useState(false)

тогда вы хотели бы добавить что-то подобное в конце вашего вызова API

.finally(() => {setIsRerender(!isRerender)})

Я НЕ рекомендую это, но я использовал это раньше, и это возможно. Но на самом деле это должно быть крайней мерой, потому что ваш код должен работать.

Если какой-либо мой код сбивает с толку или не имеет смысла, дайте мне знать, и я объясню более подробно.

Привет, спасибо за комментарий! Я решил проблему, и она не была связана с useEffect, однако я согласен, что этому методу следует отдать предпочтение.

fault 15.05.2024 23:44

Другие вопросы по теме