什么是自定义钩子?
1、自定义钩子的意图是:在组件之间共享逻辑,它可以体现你的意图,但是封装了具体的实现。
2、自定义钩子的特点:
必须以 use 开头,后跟大写字母,例如 useState或 useOnlineStatus钩子可以返回任意值。
其次,里面应当使用其他hook,否则它没有必要成为一个自定义钩子,可以直接写一个普通的函数。 这不是强制的,但是因为hook只能在顶层调用,所以明确的通过名字来表示它是或不是一个钩子是有帮助的。
每次你的组件重新渲染时,所有钩子都会重新运行。
1. 手写useLocalStorage
大概意思就是实现一个可以更新,同时又存入localStorage的hook
// 实现
const useLocalStorage = (key, initialVal) => {
// 初始值
const prev = JSON.parse(localStorage.getItem(key));
const [item, setItem] = useState(prev || initialVal);
// item值改变时存入localStorage
useEffect(() => {
localStorage.setItem(key, JSON.stringify(item));
}, [item]);
return [item, setItem];
};
// 使用方式
function App() {
const [name, setName] = useLocalStorage('name', 'Bob');
return (
<input
type="text"
value={name}
onChange={e => setName(e.target.value)}
/>
);
}
2. 手写useBodyScrollLock
实现一个useBodyScrollLock ,当出现弹窗时 阻止背景滚动
方案一:适用于全平台,通过设置背景fixed
const useBodyScrollLock = () => {
let bodyEl = document.body;
const top = useRef(0); // 注意这里要用ref
// https://www.cnblogs.com/ypppt/p/13029915.html 参考方案三全平台
function stopBodyScroll(shouldLock) {
if (shouldLock) {
top.current = window.scrollY;
bodyEl.style.position = 'fixed';
bodyEl.style.top = -top + 'px';
} else {
bodyEl.style.position = '';
bodyEl.style.top = '';
window.scrollTo(0, top.current); // 回到原先的top
}
}
const disableScroll = () => stopBodyScroll(true);
const enableScroll = () => stopBodyScroll(false);
return [disableScroll, enableScroll];
};
const [disableScroll, enableScroll] = useBodyScrollLock();
方案二:适用于pc,移动端兼容不佳
const useBodyScrollLock = () => {
const docEl = document.body;
const originalStyle = window.getComputedStyle(docEl).overflow;
useLayoutEffect(() => {
docEl.style.overflow = 'hidden';
return () => {
docEl.style.overflow = originalStyle;
};
}, []);
};Ï