我们可能会用到的一个浏览器端存储数据的工具是本地存储。在这篇文章中,我们将通过滚动我们自己的useLocalStorage钩子在React中使用本地存储。
更新
基于这篇越来越受欢迎的博文,我创建了一个npm模块,uselocalstorage 。请查看它,让我知道你的想法,并欢迎你为它做出贡献!
用npm安装。
npm install use-local-storage
用yarn安装。
yarn add use-local-storage
我们的方法
为了解决这个问题,让我们把它分解成几块。
- 提供一个本地存储的密钥。本地存储是通过键值对工作的,所以我们希望能够为我们的存储数据提供一个
key。 - 提供一个默认值。如果在所提供的
key,本地存储中没有现有的数据,我们将希望能够为我们的数据提供一个defualtValue。 - 将本地存储值加载到状态中(如果不存在本地存储值,则为默认值)。我们仍然会在我们的应用程序中维护有状态的信息,所以我们仍然可以使用
useState钩。这里的区别是,在我们考虑用户提供的defaultValue之前,我们将使用本地存储值(如果它存在)。 - 将有状态数据保存到本地存储。当我们的有状态数据发生变化时,我们要确保本地存储是最新的。因此,在我们的变量发生任何变化时,让我们运行一个效果来同步本地存储。
- 暴露状态变量和一个setter。和
useState钩子一样,我们的useLocalStorage钩子将返回一个2元素的数组。第一个元素是变量,第二个元素是该变量的设置器。
创建钩子
让我们来创建这个钩子!如上所述,该钩子将接受两个输入:key ,它将用于localStorage ;defaultValue ,它将用于localStorage ,即使还没有任何东西。
useLocalStorage.js
export const useLocalStorage = (key, defaultValue) => {};
接下来,让我们在提供的key 下加载localStorage 中的任何数据。
export const useLocalStorage = (key, defaultValue) => {
const stored = localStorage.getItem(key);
};
现在我们知道,我们的有状态变量的初始值将是这个stored 值。然而,如果在提供的key 下,localStorage 中还没有任何数据,我们将默认为用户提供的defaultValue 。
注意:由于localStorage 数据是以字符串形式存储的,我们要确保从那里检索到的任何数据都是JSON.parse 。
export const useLocalStorage = (key, defaultValue) => {
const stored = localStorage.getItem(key);
const initial = stored ? JSON.parse(stored) : defaultValue;
};
现在我们有了状态的initial 值,我们可以使用常规的useState 钩子格式,返回我们的状态变量和它的设置器。
import { useState } from 'react';
export const useLocalStorage = (key, defaultValue) => {
const stored = localStorage.getItem(key);
const initial = stored ? JSON.parse(stored) : defaultValue;
const [value, setValue] = useState(initial);
return [value, setValue];
};
几乎完成了!我们还有一个尚未满足的要求:当数据被改变时,我们需要将其保存回localStorage 。我喜欢在useEffect 钩子中做这个,当value 发生变化时,钩子会被触发。
import { useState, useEffect } from 'react';
export const useLocalStorage = (key, defaultValue) => {
const stored = localStorage.getItem(key);
const initial = stored ? JSON.parse(stored) : defaultValue;
const [value, setValue] = useState(initial);
useEffect(() => {
localStorage.setItem(key, JSON.stringify(value));
}, [key, value]);
return [value, setValue];
};
我们有了它!每当value 发生变化时,我们的效果就会运行,这意味着我们将把localStorage 项目设置为我们的value 的JSON.stringify 。请注意,所提供的key 也是我们的效果的一个依赖项,所以为了完整起见,我们把它包括在依赖项数组中,尽管我们并不指望它真的会改变。
测试我们的新钩子
让我们来测试一下我们的钩子吧我们将创建一个简单的组件,它有一个文本输入,其值是基于我们的useLocalStorage 钩子。
App.jsx
import React from 'react';
import { useLocalStorage } from './useLocalStorage';
function App() {
const [name, setName] = useLocalStorage('username', 'John');
return (
<input
value={name}
onChange={(e) => {
setName(e.target.value);
}}
/>
);
}
export default App;
现在让我们运行我们的应用程序。我们可以看到,当我们第一次运行这个应用程序时,我们的有状态的name 变量被默认为字符串John 。然而,当我们改变值,然后刷新页面时,我们现在默认为持久化的值,localStorage 。
成功了!