二. 自定义Hook
1. 认识自定义hook
自定义Hook本质上只是一种函数代码逻辑的抽取,严格意义上来说,它本身并不算React的特性。
自定义 Hook 是一个函数,其名称以 “use” 开头,函数内部可以调用其他的 Hook。
需求:所有的组件在创建和销毁时都进行打印
- 组件被创建:打印 组件被创建了;
- 组件被销毁:打印 组件被销毁了;
export default function CustomHookDemo() {
useEffect(() => {
console.log("组件被创建了");
return () => {
console.log("组件被销毁了");
}
}, [])
return (
<div>
<h2>CustomHookDemo</h2>
</div>
)
}
但是这样来做意味着所有的组件都需要有对应的逻辑:
function Home(props) {
useEffect(() => {
console.log("组件被创建了");
return () => {
console.log("组件被销毁了");
}
}, [])
return <h2>Home</h2>
}
function Profile(props) {
useEffect(() => {
console.log("组件被创建了");
return () => {
console.log("组件被销毁了");
}
}, [])
return <h2>Profile</h2>
}
如何可以对它们的逻辑进行抽取呢?
- 我们可能希望抽取到一个函数中,普通的函数中不能使用hook;
那么,我们应该如何操作呢?
- 非常简单,函数以特殊的方式命名,以 use 开头即可,将其变成自定义Hook
function useLoggingLife() {
useEffect(() => {
console.log("组件被创建了");
return () => {
console.log("组件被销毁了");
}
}, [])
}
当然,自定义Hook可以有参数,也可以有返回值:
function useLoggingLife(name) {
useEffect(() => {
console.log(`${name}组件被创建了`);
return () => {
console.log(`${name}组件被销毁了`);
}
}, [])
}
2. 自定义Hook练习
我们通过一些案例来练习一下自定义Hook。
2.1使用User、Token的Context
比如多个组件都需要使用User和Token的Context:
- 这段代码我们在每次使用user和token时都需要导入对应的Context,并且需要使用两次useContext;
import React, { useContext } from 'react'
import { UserContext, TokenContext } from '../App'
export default function CustomHookContextDemo() {
const user = useContext(UserContext);
const token = useContext(TokenContext);
console.log(user, token);
return (
<div>
<h2>CustomHookContextDemo</h2>
</div>
)
}
我们可以抽取到一个自定义Hook中:hooks/user-hook
export default function useUserContext() {
const user = useContext(UserContext);
const token = useContext(TokenContext);
return [user, token];
}
import React, { useContext } from 'react';
import useUserContext from '../hooks/user-hook';
export default function CustomContextShareHook() {
const [user, token] = useUserContext();
console.log(user, token);
return (
<div>
<h2>CustomContextShareHook</h2>
</div>
)
}
2.2获取窗口滚动的位置
在开发中,某些场景我们可能总是希望获取创建滚动的位置:
import React, { useEffect, useState } from 'react'
export default function CustomScrollPositionHook() {
const [scrollPosition, setScrollPosition] = useState(0);
useEffect(() => {
const handleScroll = () => {
setScrollPosition(window.scrollY);
}
document.addEventListener("scroll", handleScroll);
return () => {
document.removeEventListener("scroll", handleScroll);
}
}, [])
return (
<div style={{padding: "1000px 0"}}>
<h2 style={{position: "fixed", top: 0, left: 0}}>CustomScrollPositionHook: {scrollPosition}</h2>
</div>
)
}
但是如果每一个组件都有对应这样的一个逻辑,那么就会存在很多的冗余代码:
将其提取出来作为hook:
import { useState, useEffect } from 'react';
function useScrollPosition() {
const [scrollPosition, setScrollPosition] = useState(0);
useEffect(() => {
const handleScroll = () => {
setScrollPosition(window.scrollY);
}
document.addEventListener("scroll", handleScroll);
return () => {
document.removeEventListener("scroll", handleScroll)
}
}, []);
return scrollPosition;
}
export default useScrollPosition;
调用上面的自定义hook实现
import React, { useEffect, useState } from 'react'
import useScrollPosition from '../hooks/scroll-position-hook'
export default function CustomScrollPositionHook() {
const position = useScrollPosition();
return (
<div style={{padding: "1000px 0"}}>
<h2 style={{position: "fixed", left: 0, top: 0}}>CustomScrollPositionHook: {position}</h2>
</div>
)
}
2.3数据存储的localStorage
在开发中,我们会有一些数据希望通过localStorage进行存储(当然,你可以根据自己的情况选择sessionStorage)
import React, { useState, useEffect } from 'react'
export default function CustomDataStoreHook() {
const [name, setName] = useState(() => {
return JSON.parse(window.localStorage.getItem("name"))
});
useEffect(() => {
window.localStorage.setItem("name", JSON.stringify(name));
}, [name])
return (
<div>
<h2>CustomDataStoreHook: {name}</h2>
<button onClick={e => setName("gercke")}>设置name</button>
</div>
)
}
如果每一个里面都有这样的逻辑,那么代码就会变得非常冗余:
将其提取出来作为hook:
import React,{useState, useEffect} from 'react';
function useLocalStorage(key) {
const [data, setData] = useState(() => {
return JSON.parse(window.localStorage.getItem(key))
});
useEffect(() => {
window.localStorage.setItem(key, JSON.stringify(data));
}, [data]);
return [data, setData];
}
export default useLocalStorage;
调用上面的自定义hook实现
import React, { useState, useEffect } from 'react';
import useLocalStorage from '../hooks/local-store-hook';
export default function CustomDataStoreHook() {
const [name, setName] = useLocalStorage("name");
return (
<div>
<h2>CustomDataStoreHook: {name}</h2>
<button onClick={e => setName("kobe")}>设置name</button>
</div>
)
}
本文介绍了自定义Hook的基本概念,强调其作为函数代码逻辑抽取的作用。通过实例展示了如何创建自定义Hook,包括组件生命周期的打印、使用User和Token Context、获取窗口滚动位置以及localStorage数据存储。通过自定义Hook,可以减少代码冗余,提高代码复用性和可维护性。
382

被折叠的 条评论
为什么被折叠?



