2

实现一个自定义 React Hook:UseLocalStorageState

 1 year ago
source link: https://www.fly63.com/article/detial/11658
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.

更新日期: 2022-06-06阅读量: 17标签: Hook分享

扫一扫分享

大家好,我是前端西瓜哥。

最近做需求,需要将数据保存到 localStorage 里,在组件初始化的时候获取,然后修改该值的时候,要保存到本地的 localStorage 中。

倒是并不难。

function App() {
  const STORAGE_NAME = 'app_theme';
  const defaultVal = '前端西瓜哥'
  const [value, setValue] = useState(() => {
    const storage = localStorage.getItem(STORAGE_NAME);
    return storage || defaultVal;
  }) 
  const changeValue = (val) => {
    localStorage.setItem(STORAGE_NAME, val);
    setValue(val);
  }
  return (
    <div>
      <input value={value} onChange={e => changeValue(e.target.value)}/>
    </div>
  );
}

很显然,这些逻辑完全可以封装为一个 react Hook,名字很容易想到为 useLocalStorageState。

const useLocalStorageState = (key, defaultValue) => {
  const data = localStorage.getItem(key);
  const [value, setValue] = useState(data || defaultValue);
  return [
    value,
    (val) => {
      localStorage.setItem(key, val);
      setValue(val);
    }
  ];
};

逻辑并不复杂。就是在读和写的时候,加上 localStorage 的读写逻辑就好了。

用法如下:

function App() {
  const STORAGE_NAME = "app_theme";
  const defaultVal = "前端西瓜哥";
  const [value, setValue] = useLocalStorageState(STORAGE_NAME, defaultVal);
  return (
    <div>
      <input value={value} onChange={e => setValue(e.target.value)} />
    </div>
  );
}

其实这个实现还是比较粗糙的,只支持字符串格式,如果你要保存对象,需要自己手动 JSON.parse 和 JSON.stringify 来扩展了数据类型的范围。

我们可以加一下序列化和反序列化支持:

const useLocalStorageState = (key, defaultValue) => {
  const data = localStorage.getItem(key);
  const [value, setValue] = useState(JSON.parse(data || defaultValue));
  return [
    value,
    (val) => {
      localStorage.setItem(key, JSON.stringify(val));
      setValue(val);
    }
  ];
};
// 使用
function App() {
  const STORAGE_NAME = "app_theme";
  const defaultVal = { name: "前端西瓜哥" };
  const [value, setValue] = useLocalStorageState(STORAGE_NAME, defaultVal);
  return (
    <div>
      <input
        value={value.name}
        onChange={(e) => setValue({ name: e.target.value })}
      />
    </div>
  );
}

另外,JSON 序列化和反序列方法如果不够用,我们可以再加个自定义序列反序列化方法:

const useLocalStorageState = (key, defaultValue, serializer, deserializer) => {
  defaultValue = localStorage.getItem(key) || defaultValue;
  const [value, setValue] = useState(
    deserializer ? deserializer(defaultValue) : JSON.parse(defaultValue)
  );
  return [
    value,
    (val) => {
      localStorage.setItem(
        key,
        serializer ? serializer(val) : JSON.stringify(val)
      );
      setValue(val);
    }
  ];
};

其实优秀的第三方 React Hook 库 ahooks 也有这个实现,我还是建议大家用一些比较成熟的轮子,我这里只是提供一下思路。

ahooks 的 useLocalStorageState 的源码:https://github.com/alibaba/hooks/blob/v3.4.0/packages/hooks/src/useLocalStorageState/index.ts。

来源: https://www.toutiao.com/article/7103547075966566923/

链接: https://www.fly63.com/article/detial/11658


About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK