#javascript #reactjs
#javascript #reactjs
Вопрос:
У меня проблема в том, что когда мой код автоматически обновляется после сохранения файла в VS Code theText
и theBtn
возвращает целевые элементы, а на странице отображается содержимое, и все работает нормально. Но всякий раз, когда я обновляю страницу вручную, на странице отображается содержимое, но когда я нажимаю theBtn
элемент, чтобы развернуть текст, theText
и theBtn
становится пустым, и страница завершается ошибкой с сообщением «невозможно прочитать свойство undefined».
Я пытался найти причину, но не смог. Кто-нибудь, пожалуйста, помогите. Спасибо.
import { React, useEffect, useState } from 'react';
import places from '../data/places';
const Tours = () => {
return (
<>
<div className="my-20 mx-auto bg-blue-100 " style={{ height: "100%" }}>
<h1 className="text-5xl capitalize text-center font-semibold">our tours</h1>
<hr className="w-20 place-self-center mx-auto border-2 mb-12 mt-2 border-green-600" />
<Tuor cTime={new Date().getTime().toString()} />
</div>
</>
)
}
const Tuor = (props) => {
const [tuors, setTours] = useState(places);
const theText = document.querySelectorAll(".theText")
const theBtn = document.querySelectorAll(".theBtn")
console.log(theText);
console.log(theBtn);
const expandText = (index) => {
if (theBtn[index].innerHTML === "read more") {
theText[index].style.maxHeight = "50rem";
theBtn[index].innerHTML = "show less";
} else if (theBtn[index].innerHTML === "show less") {
theText[index].style.maxHeight = "6rem";
theBtn[index].innerHTML = "read more";
}
}
const removePlace = (id) => {
const newTours = tuors.filter((place) => {
return place.id !== id;
});
setTours(newTours);
}
return (
<>
{
tuors.map((place, index) => {
let price = new Intl.NumberFormat().format(place.price);
return (
<>
<div key={index} className="flex flex-col w-2/4 mx-auto bg-white shadow-2xl mb-10">
<div>
<img src={place.image} alt={place.title} />
</div>
<div className="flex mt-10">
<div className="flex justify-start w-3/4 pl-10">
<p className="tracking-widest capitalize font-bold">{place.title}</p>
</div>
<div className="flex justify-end w-1/4 pr-10"><p className="bg-blue-50 tracking-wider p-1 rounded-lg font-bold text-blue-400">N{price}</p></div>
</div>
<div className="my-5 px-10 py-2">
<p className="text-gray-500 theText">{place.description}</p><button className="text-blue-500 capitalize theBtn" onClick={() => expandText(index)}>read more</button>
</div>
<button className="ring-1 ring-red-600 text-red p-1 rounded-sm w-48 mx-auto capitalize my-12" onClick={() => removePlace(place.id)}>not interested</button>
</div>
</>
)
})
}
</>
)
}
export default Tours;
Комментарии:
1. что такое идентификатор места?
2. идентификатор места — это число (от 1 до 9). импортированный модуль places представляет собой массив объектов
3. Эй, не могли бы вы, пожалуйста, создать изолированную среду кода для лучшего понимания? Здесь, codesandbox.io/
4. codesandbox.io/s/wizardly-lichterman-y93n5?file=/src/tuors.js вот ссылка на код в condesandbox.
Ответ №1:
Используйте getElementsByClassName
вместо querySelectorAll
, поскольку он выдает object
вместо array of elements
при первоначальном рендеринге.
Я нахожу это поведение действительно странным, но когда я прочитал об этом, я узнал о
Поскольку querySelectorAll() возвращает список, который является статическим с момента его вызова, его список элементов не может быть обновлен после этого, даже если изменения вносятся в DOM динамически. Сравните это с getElementsByClassName() , который возвращает совпадающие наборы элементов в любой момент, когда он вызывается. Если вы вносите изменения в DOM «на лету», список, возвращаемый getElementsByClassName(), будет обновляться динамически.
querySelectorAll
ВОЗВРАТstatic NodeList object
getElementsByClassName
возвращаетHTML Collection
динамический
Вот ссылка на код: https://codesandbox.io/s/mystifying-wood-slqs4?file=/src/tuors.js
You can read more about differences at
https://unicorntears.dev/posts/queryselectorall-vs-getelementsbyclassname/
Комментарии:
1. Большое вам спасибо. Это действительно сработало. Мне было бы очень сложно разобраться в этом. Еще раз спасибо за ссылку, чтобы прочитать разницу. Я уверен, что так и будет.
2. Приятно слышать, что это действительно помогло. Добро пожаловать 🙂
3. Я вижу, что вы использовали
useEffect()
empty, почему это было? ИuseRef()
cnt.current, который яconsole.log
извлек, возвращал 1 каждый раз, когда я запускал код. Не могли бы вы объяснить, почему вы это использовали? Спасибо4. Я отлаживал, поэтому добавил его. Нет необходимости его использовать. Вы можете удалить его.
5. Хорошо, спасибо за добрые и полезные ответы.