Я изучаю React Hooks и хочу обновить вызов API, когда пользователь вводит текст в поле поиска. Что-то вроде живого поиска. Я понял, что событие срабатывает только при загрузке страницы, но как мне это решить?
Образец здесь: https://codesandbox.io/s/6x1xp57zmk
import React, {useState, useEffect} from 'react';
function App() {
const [cardNames, setCardName] = useState([])
const rezCards = async () => {
//const rez = await fetch('https://api.scryfall.com/cards?page=3')
const rez = await fetch ('https://api.scryfall.com/catalog/card-names')
const json = await rez.json()
setCardName(json.data)
}
useEffect(() => {
rezCards()
},[])
return <ul>{cardNames
.slice(0,50)
.map(
(cardName) => {
return <li key = {cardName}>{cardName}</li>
}
)}</ul>
}
export default App





Проблема может быть здесь:
useEffect(() => {
rezCards()
},[])
Вы оставили второй аргумент в виде пустого массива, из-за чего useEffect запускается только один раз, когда компонент монтируется, точно так же, как componentDidMount.
Если вы хотите запускать useEffect всякий раз, когда изменяется состояние, вы можете добавить состояние в качестве зависимости для хука, например
const { callThisEffectWhenThisValueIsChanged, changeValue } = useState('');
useEffect(() => {
// Do anything with here, for eg call APIs
},[callThisEffectWhenThisValueIsChanged])
changeValue(newValue);
Таким образом, в вашем коде CodeSandbox все, что вам нужно сделать, это добавить свой searchInput в зависимость, и он будет снова вызывать хук каждый раз при изменении ввода поиска.
useEffect(() => {
rezCards();
}, [searchInput]);
Всегда помните, что всякий раз, когда ваш эффект использует какое-либо состояние, вам нужно добавить состояние в качестве зависимости для хуков эффекта.
Вы можете найти дополнительную информацию в Документ React Hook
привет @BrianPaskoff, если вы проверите консоль в CodeSandbox, вы увидите много ошибок дублирования key для рендеринга, поэтому некоторые теги <li> будут просто повторно использовать предыдущее значение, то есть данные Пикачу. Попробуйте заменить <li key = {cardName.name}> на <li key = {cardName.id}>, что должно быть уникальным.
Вы можете проверить reactjs.org/docs/reconciliation.html#keys для получения более подробной информации о том, как ключ работает в React.
Вау, я не знал, что ключи так важны, я думал, что это идентификаторы, которые были настоятельно рекомендуется, чтобы код был более читаемым, но не то, что нужно для того, чтобы все это работало. Теперь работает как задумано, спасибо!
В самом деле, если мы не знаем об этом, это вызовет любой нежелательный результат :) Не забудьте проголосовать за ответ, если он покажется вам полезным! Хорошего дня!
Есть кое-что, что вы должны посмотреть. Чтобы предотвратить многократные вызовы API при наборе текста в поле поиска, используйте технику под названием debounce, вы можете добиться этого с помощью хуков реакции:
function useDebounce(value, delay) {
const [debouncedValue, setDebouncedValue] = useState(value);
useEffect(
() => {
const handler = setTimeout(() => {
setDebouncedValue(value);
}, delay);
return () => {
clearTimeout(handler);
};
},
[value, delay],
);
return debouncedValue;
}
function App() {
const debouncedInput = useDebounce(searchInputValue, 300);
useEffect(() => {
rezCards()
},[debouncedInput])
}
Эй, это работает! Но он ДОБАВЛЯЕТ к результатам, а не заменяет его, поэтому он начинается с кучи карт Пикачу, и если я набираю «чармандер», он добавляет все карты с «ча» в их именах (чемпион и т. д.) и так далее, как я введите больше букв. Как я могу сбросить состояние там?