Как я могу обновить вызов API при повторном рендеринге?

Я изучаю 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
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Навигация по приложениям React: Исчерпывающее руководство по React Router
Навигация по приложениям React: Исчерпывающее руководство по React Router
React Router стала незаменимой библиотекой для создания одностраничных приложений с навигацией в React. В этой статье блога мы подробно рассмотрим...
Массив зависимостей в React
Массив зависимостей в React
Все о массиве Dependency и его связи с useEffect.
0
0
68
2
Перейти к ответу Данный вопрос помечен как решенный

Ответы 2

Проблема может быть здесь:

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

Эй, это работает! Но он ДОБАВЛЯЕТ к результатам, а не заменяет его, поэтому он начинается с кучи карт Пикачу, и если я набираю «чармандер», он добавляет все карты с «ча» в их именах (чемпион и т. д.) и так далее, как я введите больше букв. Как я могу сбросить состояние там?

Brian Paskoff 22.04.2019 04:57

привет @BrianPaskoff, если вы проверите консоль в CodeSandbox, вы увидите много ошибок дублирования key для рендеринга, поэтому некоторые теги <li> будут просто повторно использовать предыдущее значение, то есть данные Пикачу. Попробуйте заменить <li key = {cardName.name}> на <li key = {cardName.id}>, что должно быть уникальным.

Ewe Tek Min 22.04.2019 05:10

Вы можете проверить reactjs.org/docs/reconciliation.html#keys для получения более подробной информации о том, как ключ работает в React.

Ewe Tek Min 22.04.2019 05:11

Вау, я не знал, что ключи так важны, я думал, что это идентификаторы, которые были настоятельно рекомендуется, чтобы код был более читаемым, но не то, что нужно для того, чтобы все это работало. Теперь работает как задумано, спасибо!

Brian Paskoff 22.04.2019 05:16

В самом деле, если мы не знаем об этом, это вызовет любой нежелательный результат :) Не забудьте проголосовать за ответ, если он покажется вам полезным! Хорошего дня!

Ewe Tek Min 22.04.2019 05:22
Ответ принят как подходящий

Есть кое-что, что вы должны посмотреть. Чтобы предотвратить многократные вызовы 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])
}

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