React useState не обновляет состояние

Я тренирую React Hooks с помощью приложения для фильмов, и теперь я столкнулся с проблемой. Когда я нажимаю кнопку в компоненте Header, должно произойти изменение состояния путем очистки массива itemsList. Код фактически подготовлен для кнопки Load More, которая добавит дополнительные элементы в этот массив, когда запрос API используется с другим компонентом (еще не представленным). Проблема в том, что массив не очищен, и когда какая-то кнопка нажимается, в него добавляются элементы из que API Request.

Это файл App.js

import React, { useState } from "react";
import axios from "axios";
import Header from "./Containers/Header";

export default function App() {
  const [values, setValues] = useState({
    msdb: "API_CODE",
    page: 1,
    totalPages: 0,
    listType: "popular",
    mode: "movie",
    itemsList: [],
    searchFiled: "",
    loading: false,
    error: false
  });
  const { msdb, page, totalPages, listType, mode, itemsList, searchFiled, loading, error } = values;

  const modeSelection = (event) => {
    let modeType = "";
    let selectedMode = event.target.innerText;
    console.log(selectedMode);
    if (selectedMode === "Movies") {
      modeType = "movie";
    } else if (selectedMode === "Series") {
      modeType = "tv";
    }
    setValues((prevValues) => {
      return { ...prevValues, mode: modeType, itemsList: [] };
    });
    let endPoint = `https://api.themoviedb.org/3/${mode}/${listType}?api_key=${msdb}&page=${page}`;
    fetchItems(endPoint);
  };

  const fetchItems = (endPoint) => {
    axios
      .get(endPoint)
      .then((response) => {
        const newItemsList = [...itemsList];
        const newItems = response.data.results;
        if (newItems) {
          setValues((prevValues) => {
            return {
              ...prevValues,
              page: response.data.page,
              itemsList: [...newItemsList, ...newItems],
              loading: false,
              totalPages: response.data.total_pages
            };
          });
        }
      })
      .catch((error) => {
        setValues({ ...values, error: true });
        console.log(error);
      });
  };

  return (
    <div className="App">
      <Header mode={modeSelection} />
    </div>
  );
}

А это файл Header.js

import React from "react";
import "./Header.css";
import { NavLink } from "react-router-dom";

export default function Header(props) {
  return (
    <div>
      
        <div className="top-center">
          <NavLink to="/movies" onClick={props.mode} className="ch-button">
            Movies
          </NavLink>
          <NavLink to="/series" onClick={props.mode} className="ch-button">
            Series
          </NavLink>
        </div>
        
    </div>
  );
}

Итак, я хотел бы, чтобы результат был следующим: при нажатии на кнопки компонента Header массив itemsList должен быть очищен, и запрос API заполнит его снова. Помните, что метод axios уже подготовлен для кнопки «Загрузить больше» в другом компоненте, и в этом случае он добавит больше элементов в массив. Должен ли быть где-то useEffect? Спасибо


person r_gon    schedule 29.09.2020    source источник


Ответы (1)


Проблема заключается в асинхронном характере setState. Вы правильно используете prevState для установки нового, но в 'fetchItems' при установке новых элементов вы получаете старые из текущего состояния, а не prevState. Таким образом, состояние еще не обновляется с помощью пустого массива, когда вы используете его для установки новых элементов. Ты можешь попробовать

        if (newItems) {
          setValues((prevValues) => {
            return {
              ...prevValues,
              page: response.data.page,
              itemsList: [...prevState.itemsList, ...newItems],
              loading: false,
              totalPages: response.data.total_pages
            };
          });
        }
person Anastasiia Solop    schedule 29.09.2020
comment
Это сработало! Почему добавление const modeSelection = async (event) = ›{.... и await setValues ​​... не работает? - person r_gon; 29.09.2020
comment
Это причуда Reactjs. Состояние установки всегда асинхронно, но сама функция не возвращает обещание. Так что вы не можете этого дождаться. - person Anastasiia Solop; 30.09.2020