Как использовать знаменитый «prevState» для изменения нашего состояния React без его переопределения!

Начнем с базового примера (счетчик -famous-):

Со свежим новым приложением React:

import "./App.css";
import React, { useState } from "react";
const App = () => {
const [mySuperCounter, setMySuperCounter] = useState(0);
const handleIncrement = () => {
setMySuperCounter(mySuperCounter + 1);
setMySuperCounter(mySuperCounter + 1);
setMySuperCounter(mySuperCounter + 1);
};
const handleReset = () => {
setMySuperCounter(0);
};
return (
 <div className="App">
  <div>
   <button
   className="super-button"
   type="submit"
   onClick={handleIncrement}>
   Incrementor
   </button>
   <button className="super-button" type="submit" onClick=          {handleReset}>
State Resettor
   </button>
  </div>
  <div>{mySuperCounter}</div>
</div>
);
};
export default App;

Хорошо, у нас есть базовый компонент с состоянием «mySuperCounter» и две кнопки, одна для увеличения, другая для сброса моего состояния на 0.

Если мы посмотрим на метод handleIncrement, мы можем подумать, что состояние будет увеличиваться на 3 каждый раз, когда я нажимаю кнопку «Incrementor».

Вместо этого мы просто увеличиваем на единицу. Почему ? Потому что наша функция setState переопределит предыдущее состояние, чтобы создать новое ... Итак, мы переопределим наше начальное состояние в 3 раза на единицу, дадим нам волшебный результат ... .one.

Теперь давайте посмотрим, как мы можем добавить к предыдущему состоянию:

Я просто пропущу здесь свой метод handleIncrement:

const handleIncrement = () => {
setMySuperCounter((prev) => prev + 1);
setMySuperCounter((prev) => prev + 1);
setMySuperCounter((prev) => prev + 1);
};

Вот так ! Теперь, если мы нажмем на нашу кнопку «Инкрементатор», мы увеличим наш счетчик на 3.

Почему ? Поскольку наш аргумент «prev» передан функции обратного вызова нашего setState.

В нашем случае «prev» равно предыдущему состоянию, поэтому построчно мы увеличиваем 0 на 1, 1 на 1, 2 на 1 = ›Результат: 3

Это базовый пример, давайте взглянем на более сложный !!

Добавьте ключ / значение из массива в массив объекта:

Давайте смоделируем вызов API с обещанием:

// sections.js
const mySections = () => {
 return Promise.resolve([
  { id: 1, title: "My First Section" },
  { id: 2, title: "My Second Section" },
] );
};
export default mySections;

Затем преобразуйте наш App.js для выполнения вызова с useEffect и сохраните результат в состоянии:

// App.js
import "./App.css";
import React, { useEffect, useState } from "react";
import mySections from "./sections";
const App = () => {
 const [sections, setSections] = useState([]);
  useEffect(() => {
   const loadSections = async () => {
    return await mySections();
   };
   loadSections().then((res) => {
    setSections(res);
   });
  }, []);
 return <div className="App"></div>;
};
export default App;

Давайте создадим другое обещание в другом файле для имитации другого вызова API, мы получим данные, которые мы хотели бы отправить в разделах выше, в зависимости от section_id.

// tools.js
const myTools = () => {
return Promise.resolve([
{ id: 1, title: "My Super first tools", section_id: 1 },
{ id: 2, title: "My Super second tools", section_id: 2 },
{ id: 3, title: "My Super third tools", section_id: 1 },
{ id: 4, title: "My Super fourth tools", section_id: 2 },
{ id: 5, title: "My Super fifth tools", section_id: 1 },
{ id: 6, title: "My Super sixth tools", section_id: 2 },
{ id: 7, title: "My Super seventh tools", section_id: 1 },
{ id: 8, title: "My Super eighth tools", section_id: 2 },
]);
};
export default myTools;

Затем нам нужно изменить файл App.js:

//App.js
const App = () => {
 const [sections, setSections] = useState([]);
  useEffect(() => {
   const loadSections = async () => {
    return await mySections();
   };
   loadSections().then((res) => {
    setSections(res);
   });
   const loadToolsIntoSections = async () => {
    return await myTools();
   };
   loadToolsIntoSections().then((response) => {
     setSections((prev) => {
      return prev.map((section) => {
       return {
        ...section,
        tools: response.filter((tool) => {
         return tool.section_id === section.id;
        }),
       };
      });
     });
    });
   }, []);
   return <div className="App"></div>;
};
export default App;

Объяснение:

Мы вызываем метод loadToolsIntoSections, который представляет собой другое моделирование вызова API.

Мы повторно используем метод setSections и передаем аргумент «prev» в функцию обратного вызова. (сохраняем предыдущее состояние)

Мы сопоставляем массив разделов, чтобы взаимодействовать с каждым объектом в нем.

Мы используем оператор распространения, чтобы создать другой объект, и мы добавляем другие ключевые «инструменты».

Мы используем ответ OUF API Call для фильтрации каждого инструмента, в котором section_id совпадает с идентификатором фактического раздела.

Таким образом, вы можете отправлять все инструменты в соответствующие разделы.

Надеюсь, это поможет понять, как легко использовать prevState!