Как использовать знаменитый «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!