ReactJS: очистить старые извлеченные данные компонента перед повторной выборкой - PullRequest
0 голосов
/ 04 февраля 2020

Я получаю удаленные данные из моего компонента React. Когда данные готовы, дочерние компоненты отображаются. Во время загрузки данных отображается текст «Данные загружаются ....».

Когда компонент визуализируется во второй раз из-за изменения props, я устанавливаю предыдущие данные на null для того, чтобы показать, что загружаются новые данные.

const List = (props) => {
  const [items, setItems] = useState(null);

  useEffect(() => {  
    setItems(null);

    fetch(`http://some_url_to_fetch_items.com?PAGE=${props.page}`)
    .then((data) => {
       setItems(data);
    })   
  }, [props.page]);

  if (!items) {
    return "Data is loading ......."
  }

  return (
    <ul>
      {items.map(item => (
        <li>{item}</li>
      ))}
    </ul>
  )
}

Проблема этого подхода заключается в том, что при повторном рендеринге компонента код setItems(null); выполняется не сразу (возможно, потому что useEffect выполняется асинхронно), и компонент повторно выполняет рендеринг 3 раза вместо ожидаемого 2:

  • 1-й повторный рендеринг из-за смены реквизита (НО со старыми данными, поскольку setItems(null) выполняется слишком поздно)
  • 2-й повторный рендеринг после окончательного выполнения setItems(null)
  • 3-й повторный рендеринг после извлечения данных

Я понимаю, что проблема с моим подходом Но я не вижу другого пути. Обязательно использовать крючки.

Есть идеи?

Ответы [ 2 ]

1 голос
/ 06 февраля 2020

Быстрое решение состоит в том, чтобы добавить ключевую опору в ваш список:

<List key={page} page={page} />

Когда значение для страницы изменится, компонент List будет размонтирован, а новый отрендерен. В новом не будет никаких предыдущих данных, поэтому вы получите только 2 рендера вместо 3.

Это означает, что вам больше не нужно устанавливать предыдущие данные на null.

Если вы сделаете это, вам нужно проверить, что компонент все еще смонтирован в вашем useEffect перед вызовом setItems, в противном случае вы будете пытаться установить состояние на размонтированном компоненте. Вы можете написать:

if(setItems) {
  setItems(data)
}

Изменение ключевого реквизита немного странно, поэтому я бы рассмотрел другие способы решения вашей проблемы.

Возможно, вам следует вместо этого передать данные в список списка, отвечающего за выборку данных, и состояния страницы и данных внутри родительского компонента?

Пока что изменение ключа с помощью страницы должно работать.

0 голосов
/ 06 февраля 2020
use this method  : 

  useEffect(() => {  
       fetch(`http://some_url_to_fetch_items.com?PAGE=${props.page}`)
        .then((data) => {
           setItems(data);
        })   
      }, []);

     return (
        <ul>
          {items? items.map(item => (
            <li key={item.id}>{item}</li>
          )):"Data is Loading..."}
        </ul>
      )
...