Использование localStorage с React Hooks

Использование localStorage с React Hooks

От автора: localStorage — это один из двух механизмов веб-хранилища браузера. Он позволяет пользователям сохранять данные в виде пар ключ / значение в браузере для последующего использования.

В отличие от механизма sessionStorage, который сохраняет данные в хранилище браузера, пока открыта текущая вкладка браузера, localStorage не очищает данные при закрытии браузера. Это делает его идеальным для хранения данных, не привязанных к текущей вкладке браузера.

Разработчики часто реализуют localStorage при добавлении функции темного режима в приложение, сохранении элемента списка дел или сохранении значений формы ввода пользователя, среди многих других вариантов использования.

В этом руководстве мы расскажем, как использовать localStorage для сохранения данных формы ввода в хранилище браузера с помощью React Hooks. Мы также расскажем, как создать собственный React Hook, чтобы разделять схожую логику между несколькими компонентами.

Первоначальная настройка проекта с использованием localStorage

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

npx create-react-app localstorage-react-hook

После создания папки проекта откройте ее в редакторе кода и запустите сервер разработки, выполнив команду npm start. Проект должен запуститься в браузере по адресу http://localhost:3000/.

Создание компонента формы React

Как упоминалось ранее, мы будем использовать localStorage для сохранения данных формы ввода в хранилище браузера. Как и любое приложение React, наше внимание сосредоточено на папке src. Итак, давайте удалим все файлы внутри src и создадим файл index.js внутри src. Затем добавьте в index.js следующий код:

import React from "react";
import ReactDOM from "react-dom"; import App from "./components/App";
// styles
import "./app.css"; ReactDOM.render( <React.StrictMode> <App /> </React.StrictMode>, document.getElementById("root")
);

Обратите внимание, что мы импортировали файл CSS, чтобы добавить стиль в приложение. Итак, давайте создадим папку app.css в папке src.

Скопируйте стили из проекта localstorage-react-hook-project и добавьте их в файл app.css. Затем создайте папку components в папке src для хранения файлов компонентов. Затем добавьте файл App.js и файл Form1.js. Файл App.js является корневым и родительским компонентами, а Form1.js будет содержать входные данные формы. Добавьте следующий код в файл components/App.js:

import Form1 from "./Form1"; const App = () => { return ( <div className="container"> <h1>localStorage with React hooks</h1> <Form1 /> </div> );
};
export default App;

И, наконец, добавьте этот код в файл components/Form1.js:

import { useState } from "react"; const Form1 = () => { const [name, setName] = useState(""); return ( <form> <input type="text" value={name} onChange={(e) => setName(e.target.value)} placeholder="Full name" aria-label="fullname" /> <input type="submit" value="Submit"></input> </form> );
}; export default Form1;

После сохранения файлов протестируйте проект, и вы должны увидеть этот рендеринг:

Использование localStorage с React Hooks

Приведенный выше код является простейшей реализацией входных данных формы в React. Используя React Hook useState для управления компонентом, мы поддерживаем актуальность состояния ввода при каждом нажатии клавиши, как показано выше.

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

Сохранение данных формы ввода в localStorage

localStorage дает нам доступ к объекту хранилища браузера. У объекта Storage есть методы для сохранения, чтения и удаления данных, а также многих других действий.

Чтобы увидеть список методов Storage, откройте консоль браузера и введите localStorage. После нажатия клавиши ввода методы становятся доступными в prototype объекта Storage.

Использование метода setItem()

Чтобы сохранить данные ввода формы в хранилище браузера, мы должны вызвать метод хранения setItem(), используя следующий синтаксис:

localStorage.setItem("key", "value")

Хранилище браузера принимает только строки. Поэтому, для значений разных типов данных, таких как объект или массив, мы должны преобразовать его в строку JSON с помощью JSON.stringify().

Использование хука useEffect

Мы также можем использовать React Hook useEffect для выполнения таких эффектов как сохранение данных в хранилище браузера. Это делает этот хук идеальным местом для вызова метода setItem. Откройте файл components/Form1.js и добавьте следующий код над оператором return:

useEffect(() => { // storing input name localStorage.setItem("name", JSON.stringify(name));
}, [name]);

Убедитесь, что вы импортировали useEffect из React следующим образом:

import { useState, useEffect } from "react";

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

const [name, setName] = useState("");

Использование JSON.stringify в setItem необязательно при сохранении строковых данных в хранилище:

localStorage.setItem("name", JSON.stringify(name));

Однако JSON.stringify требуется, если значение представляет собой другой тип данных, например объект или массив. Теперь сохраните файл и протестируйте проект; мы должны увидеть следующее:

Использование localStorage с React Hooks

При каждом нажатии клавиши входное значение сохраняется в локальном хранилище, потому что хук useEffect, содержащий метод хранилища setItem, запускается при рендеринге первого компонента и после каждого изменения состояния.

Однако при перезагрузке страницы значение в хранилище возвращается к пустой строке. Это происходит потому, что мы присвоили переменной состояния name пустую строку по умолчанию. Следовательно, React использует пустое значение при первоначальном рендеринге.

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

Чтение данных из localStorage

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

Использование метода getItem()

Обновите хук useState в файле components/Form1.js:

const [name, setName] = useState(() => { // getting stored value const saved = localStorage.getItem("name"); const initialValue = JSON.parse(saved); return initialValue || "";
});

Мы используем метод хранения getItem() для извлечения данных из локального хранилища. JSON.parse (), используемый в коде, десериализует возвращенную строку JSON из хранилища.

Оба, и JSON.Stringify, и JSON.parse необязательны при работе со строковыми значениями (как показано в нашем случае). Однако они требуются для других типов данных, таких как объекты и массивы.

Сохраните файл и протестируйте проект. Входные данные должны быть доступны в поле формы при перезагрузке страницы или последующем посещении страницы.

Использование localStorage с React Hooks

Создание пользовательского React Hook для сохранения входных данных формы

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

Хотя мы можем легко скопировать логику из уже созданной и использовать ее в новом компоненте, это не всегда практически осуществимо, особенно если мы решим создать больше входных данных.

Вместо этого React позволяет нам извлекать и совместно использовать аналогичную логику между компонентами с помощью пользовательских хуков.

В этом разделе мы узнаем, как создать собственный хук для сохранения входных данных формы в нескольких компонентах.

Начнем с создания еще одной формы. В папке src/components создайте новый файл с именем Form2.js и добавьте следующий код:

import { useState } from "react"; const Form2 = () => { const [name, setName] = useState(""); const [checked, setChecked] = useState(false); return ( <form> <input type="text" value={name} onChange={(e) => setName(e.target.value)} placeholder="Full name" aria-label="fullname" /> <label> <input type="checkbox" checked={checked} onChange={(e) => setChecked(e.target.checked)} />{" "} Not a robot? </label> <input type="submit" value="Submit"></input> </form> );
}; export default Form2;

Затем импортируйте и используйте компонент в файле components/App.js:

// ...
import Form2 from "./Form2"; const App = () => { return ( <div className="container"> {/* ... */} <Form2 /> </div> );
};
export default App;

Сохраните файлы и просмотрите форму в интерфейсе.

Использование localStorage с React Hooks

Взаимодействие с этой формой не сохраняет значение состояния в localStorage, поскольку у нас еще нет логики. Итак, давайте определим единую логику для управления всеми входными данными формы.

Разработка логики localStorage

Чтобы начать работать над логикой localStorage, создайте файл с именем useLocalStorage.js в папке src и добавьте следующий код:

import { useState, useEffect } from "react"; function getStorageValue(key, defaultValue) { // getting stored value const saved = localStorage.getItem(key); const initial = JSON.parse(saved); return initial || defaultValue;
} export const useLocalStorage = (key, defaultValue) => { const [value, setValue] = useState(() => { return getStorageValue(key, defaultValue); }); useEffect(() => { // storing input name localStorage.setItem(key, JSON.stringify(value)); }, [key, value]); return [value, setValue];
};

Присмотревшись к приведенному выше коду, мы только извлекли логику хранения из файла components/Form1.js. Ничего особенного мы не сделали.

Создавая собственный хук под названием useLocalStorage, мы поддерживаем всю логику хранения, которая есть в компоненте Form1.

Хук useLocalStorage ожидает два аргумента: key и defaultValue. Это означает, что мы ожидаем передать эти значения при вызове хука в наших компонентах.

Обратите внимание, что вы можете назвать свой собственный хук как угодно, но убедитесь, что вы начинаете с use.

Использование пользовательского хука useLocalStorage

В файле components/Form1.js замените логику над оператором return пользовательским хуком, чтобы у вас было следующее:

import { useLocalStorage } from "../useLocalStorage"; const Form1 = () => { const [name, setName] = useLocalStorage("name", ""); return ( <form> {/* ... */} </form> );
}; export default Form1;

После импорта пользовательского хука мы можем использовать его и передать уникальный ключ и значение по умолчанию, которое в данном случае является пустой строкой. Если мы сделаем то же самое для компонента Form2 в файле components/Form2js, у нас должно получиться следующее:

import { useLocalStorage } from "../useLocalStorage"; const Form2 = () => { const [name, setName] = useLocalStorage("name2", ""); const [checked, setChecked] = useLocalStorage("checked", false); return ( <form> {/* ... */} </form> );
}; export default Form2;

Сохраните все файлы и протестируйте проект. Мы должны иметь возможность сохранять все входные данные формы в localStorage.

Использование localStorage с React Hooks

Проблемы с доступом к localStorage для отрисованного на стороне сервера приложения

При работе с фреймворком, подобным Next.js, который выполняет код на стороне сервера, во время использования localStorage появляется сообщение об ошибке «окно не определено».

LocalStorage, используемый в нашем коде, является встроенным свойством window.localStorage объекта window.
В нашем коде мы проигнорировали window при доступе к localStorage, потому что это глобальный объект; мы можем выбирать включение объекта window или нет, потому что это необязательно.

Объект window доступен не на стороне сервера, а на стороне клиента / браузера, что вызывает ошибку. Чтобы исправить ошибку на стороне сервера, проверьте, определен ли объект window или нет. Таким образом, наш код работает только в среде, в которой доступен объект window.

Откройте файл src/useLocalStorage.js и обновите функцию getStorageValue(), чтобы у вас было следующее:

function getStorageValue(key, defaultValue) { // getting stored value if (typeof window !== "undefined") { const saved = localStorage.getItem(key); const initial = saved !== null ? JSON.parse(saved) : defaultValue; return initial; }
}

Не забывайте, что мы также использовали localStorage внутри хука useEffect в файле useLocalStorage.js. Но в этом случае localStorage безопасен, потому что хук useEffect работает только на стороне клиента, где у нас есть доступ к объекту window. Протестируйте проект, чтобы убедиться, что все работает должным образом.

Заключение

Мы рассмотрели, как использовать localStorage для сохранения данных в браузере с помощью React Hooks. Мы также узнали, как создать собственный хук для извлечения логики компонента в функции многократного использования. Полный исходный код проекта можно найти здесь.

Автор: Ibadehin Mojeed

Источник: blog.logrocket.com

Редакция: Команда webformyself.

Читайте нас в Telegram, VK, Яндекс.Дзен