1 useSetState
使用
可以在函数式组件中使用类组件的setState
仿写
import { useCallback, useState } from "react";
// 使用类组件的setState
const useClassState = (initialState) => {
// 先把传入的state使用函数式的useState定义上
const [state, setState] = useState(initialState);
// 使用usecallback防止重复创建函数
const mergeState = useCallback((patch) => {
setState((prevState) => {
// 如果传入的是函数的话,就调用传入的函数来生成新的state
const newState = typeof patch === "function" ? patch(prevState) : patch;
// 类的setState是合并
return newState ? { ...prevState, ...patch } : prevState;
});
}, []);
return [state, mergeState];
};
export default useClassState;
2 useToggle
使用
const [state, { toggle, set, setLeft, setRight }] = useToggle('Hello', 'World');
传入两个值,setLeft将值切换成第一个,setRight将值切换成第二个,set可以随意设置值,toggle则来回切换
仿写
import { useMemo, useState } from "react";
/**
*
* @param {*} firstState 第一个值
* @param {*} secondState 第二个值
* @returns [state, {
* toggle, // 切换值
* set, // 设置值
* setFirst, // 切换到第一个值
* setSecond // 切换到第二个值
* }]
*/
const useToggle = (firstState, secondState) => {
const [state, setState] = useState(firstState);
// 之后再不需要重新生成对象了
const actions = useMemo(() => {
// 如果只传了第一个值,则第二个值取反
const secondStateJudgeValue =
secondState === undefined ? !firstState : secondState;
const toggle = () =>
setState((val) =>
val === firstState ? secondStateJudgeValue : firstState
);
const set = (val) => setState(val);
const setFirst = () => setState(firstState);
const setSecond = () => setState(secondStateJudgeValue);
return { toggle, set, setFirst, setSecond };
}, []);
return [state, actions];
};
export default useToggle;
3 useCookieState
使用
const [value, setValue] = useCookieState("useCookieStateOptions", {
defaultValue: "0",
path: "/",
expires: (() => new Date(+new Date() + 10000))(),
});
setValue((v) => String(Number(v) + 1), {
expires: (() => new Date(+new Date() + 10000))(),
});
内部借助了js-cookie
初始化不会加入cookie中
仿写
import { useState } from "react";
import Cookies from "js-cookie";
const useCookie = (key, value, options = {}) => {
const [state, setState] = useState(() => {
// 先检查本地是否有cookie
const localCookie = Cookies.get(key);
if (localCookie) {
return localCookie;
}
// 如果本地无cookie,则保存value
if (typeof value === "function") {
return value();
} else {
return value;
}
});
// 源码中设计的初始化不会加入cookie中,这里初始化会加入cookie
Cookies.set(key, state, options);
const updateState = (newValue, newOptions) => {
// 合并options
const nowOptions = { ...options, ...newOptions };
// 拿到value
const value = typeof newValue === "function" ? newValue(state) : newValue;
// 如果value是undefined则删除
if (value === undefined) {
Cookies.remove(key);
} else {
Cookies.set(key, value, nowOptions);
}
setState(value);
};
return [state, updateState];
};
export default useCookie;
4 useLocalstorageState & useSessionStorageState
使用
const [message, setMessage] = useLocalStorageState(
'use-local-storage-state-demo3',
{
defaultValue: 'Hello~',
serializer: (v) => v ?? '',
deserializer: (v) => v,
},
);
serializer和deserializer是自定义序列化和反序列化的函数
仿写
本hook按照自己的想法写的
import { useState } from "react";
/**
*
* @param {*} key storage的键
* @param {*} value storage的值
* @param {*} options 用户配置:
* serializer序列化函数,
* deserializer反序列化函数,
* storage为localStorage或sessionStorage
* @returns [state,
* updateState // 更新值,updateState(val),val为空则表示删除storage
* ]
*/
const useLocalStorage = (key, value, options = {}) => {
let storage = localStorage
if (options.storage === localStorage || options.storage === sessionStorage) {
storage = options.storage
}
// 如果提供了自定义序列化方法,则使用用户提供的方法
const serializer = (value) => {
if (options.serializer) {
return options.serializer(value);
} else {
return JSON.stringify(value);
}
};
const deserializer = (value) => {
if (options.deserializer) {
return options.deserializer(value);
} else {
return JSON.parse(value);
}
};
// 取数据
const getItem = () => {
const item = storage.getItem(key);
if (item) {
return deserializer(item);
} else {
return typeof value === "function" ? value() : value;
}
};
const [state, setState] = useState(getItem());
const updateState = (newValue) => {
const val = typeof newValue === "function" ? newValue() : newValue;
if (val) {
storage.setItem(key, serializer(val));
setState(getItem());
} else {
storage.removeItem(key);
}
};
return [state, updateState];
};
export default useLocalStorage;
5 useMap
使用
const [map, { set, setAll, remove, reset, get }] = useMap([
['msg', 'hello world'],
[123, 'number type'],
]);
仿写
本hook按照自己的想法写的
import { useState } from "react";
/**
*
* @param {*} itor 传入一个迭代器
* @returns [map, {
* set, // 新加
* del, // 删除
* clear, // 清除
* reset, // 重置
* setAll // 重新设置一个新的map
* }]
*/
const useMap = (itor) => {
const [map, setMap] = useState(new Map(itor));
const set = (key, val) => {
setMap((oldMap) => {
const newMap = new Map(oldMap);
newMap.set(key, val);
return newMap;
});
};
const del = (key) => {
setMap((oldMap) => {
const newMap = new Map(oldMap);
newMap.delete(key);
return newMap;
});
};
const clear = () => setMap(new Map());
const reset = () => setMap(new Map(itor));
const setAll = (newitor) => setMap(() => new Map(newitor));
return [map, { set, del, clear, reset, setAll }]
};
export default useMap;
6 useSet
使用
const [set, { add, remove, reset }] = useSet(['Hello']);
仿写
本hook按照自己的想法写的
import { useState } from "react"
/**
*
* @param {*} itor 传入一个迭代器
* @returns [set, {
* add, // 新加
* del, // 删除
* clear, // 清除
* reset, // 重置
* setAll // 重新设置一个新的set
* }]
*/
const useSet = (itor) => {
const [set, setSet] = useState(new Set(itor))
const add = (val) => {
if (set.has(val)) return;
setSet(() => {
const newSet = new Set(set)
newSet.add(val)
return newSet
})
}
const del = (val) => {
if (!set.has(val)) return;
setSet(() => {
const newSet = new Set(set)
newSet.delete(val)
return newSet
})
}
const clear = () => setSet(new Set())
const reset = () => setSet(new Set(itor))
const setAll = (newitor) => setSet(() => new Set(newitor));
return [set, { add, del, clear, reset, setAll }]
}
export default useSet
7 useResetState
使用
const [state, setState, resetState] = useResetState({
hello: '',
count: 0,
});
仿写
import { useCallback, useState } from "react"
/**
*
* @param {*} initialState 初始值
* @returns [state, setState, reset] reset:重置为初始值
*/
const useResetState = (initialState) => {
const [state, setState] = useState(initialState)
const reset = useCallback(() => {
setState(initialState)
}, [])
return [state, setState, reset]
}
export default useResetState
8 useLatest
使用
const ref = useLatest(value)
这个hook是为了能够拿到最新值,而不用产生闭包。
仿写
import { useRef } from "react";
/**
* 可以保证每次拿到最新值,防止产生大量闭包
* @param {*} value 传入的值
* @returns Ref
*/
const useLatest = (value) => {
// 创建ref,但是需要注意的是,每次重新调用useLatest这个hook,都不会再创建一个新的ref了
const ref = useRef(value);
ref.current = value;
return ref;
};
export default useLatest;
9 useDebounce
使用
返回一个函数
仿写
/**
* 实现简单的防抖
* @param {function} fn 希望做防抖的函数
* @param {*} time 防抖的时间
* @param {...any} args 其他参数,内部会被转成数组,方便apply传值
* @returns
*/
const useDebounce = (fn, time = 0, ...args) => {
let timer = null;
let that = this;
return () => {
if (timer) {
// 每次都清空上一次的计时器保证函数只会执行一次
clearTimeout(timer);
}
timer = setTimeout(() => {
// 保证this指向,args保证事件对象可以正常传入
fn.apply(that, args);
}, time);
};
};
export default useDebounce;