最近在写的 React 版记账项目关于类别和记录的数据都需要进行管理,没有使用 useReducer 全局管理数据的方式,而是采用了自定义数据管理方式,即自定义 Hooks。
- 把数据相关的操作写在一个函数
- 只暴露读写接口。
自定义 useTags hooks
以管理类别数据为例
- 初始化 tags 数组
type Tag = {id: number,genre: string,name: string,value: string}
const [tags, setTags] = useState<Tag[]>([]);
- 对数据的写操作 举个栗子:删除 id 为 xx 的 tag
const deleteTag = (id: number) => {
setTags(tags.filter(t => t.id !== id));
};
return {tags, deleteTag};
由于刷新后数据会消失,因此我们需要把数据存入 localStorage 里面
- 使用 localStorage 写数据:
window.localStorage.setItem("tagList", JSON.stringify(tags));
读数据
let localTags = JSON.parse(window.localStorage.getItem("tagList") || "[]");
当组件挂载时执行把数据从 localStorage 里面读出来并赋给 tags,且执行第一次从 0 到 有。因此我们可以使用
useEffect(() => {
setTags(JSON.parse(window.localStorage.getItem("tagList") || "[]"));
}, []);
每次 tags 有变化再把数据重新写入 localStorage,所以这部分应该是组件挂载时不执行,tags 再次变化再执行。
重点!
我创建了自定义 hooks 。即第一次不执行,变化再执行
// useUpdate.tsx
import {useEffect, useRef} from "react";
export const useUpdate = (fn: () => void, dependency: any[]) => {
const count = useRef(0);
useEffect(() => {
count.current += 1;
});
useEffect(() => {if (count.current > 1) {fn();}}, [fn, dependency]);};
形参为要执行的函数以及依赖。当通过监控 count 的值来判断是否是第一次渲染进而根据依赖的变化决定是否执行该函数
// 使用 自定义 hooks 第一次不执行 变化再执行
useUpdate(() => {
window.localStorage.setItem("tagList", JSON.stringify(tags));
}, tags);
应用
举个栗子 :在该页面我希望所有的 tag 都能显示在页面上,并且点击按钮可以实现添加 tag 的功能
import React from "react";
import {useTags} from "hooks/useTags";
const TagsSection = () => {
const {tags, addTag} = useTags();
return (
<div>
<ul>{tags.map(tag=><li key={tag.id}>{tag.name}</li>)}</ul>
<button onClick={addTag}>添加 tag </button>
</div>
);
};
export {TagsSection};
在任意想要获取或者是对 tag 数据进行操作的组件都可以直接引入自定义 hooks,是不是非常方便呢~