什么是自定义hook
Hook 是 React 16.8 的新增特性。它可以让你在不编写 class 的情况下使用 state 以及其他的 React 特性。
通过自定义 Hook,可以将组件逻辑提取到可重用的函数中
。
首先也要遵循hooks的规则
只在最顶层使用hooks
,不要在循环、条件或者嵌套中调用hook,这样就能确保hook在每一次渲染中都按同样的顺序调用。多次调用hooks可以保证hook状态的正确。只在react函数(react函数组件、自定义hook组件)中调用hook
,不要在普通的javascript函数中调用
可以使用eslint-plugin-react-hooks
来强制执行这两条规则
自定义hook的规则
本质是一个函数,以use开头
(不遵循的话,由于无法判断某个函数是否包含对其内部 Hook 的调用,React 将无法自动检查你的 Hook 是否违反了 Hook 的规则。)内部正常使用useState useEffect或者其他hooks
自定义返回结果,格式不限
在两个组件中使用相同的 Hook 不会共享 state
(自定义 Hook 是一种重用状态逻辑的机制(例如设置为订阅并存储当前值),所以每次使用自定义 Hook 时,其中的所有 state 和副作用都是完全隔离的。)每次调用 Hook,它都会获取独立的 state
(从 React 的角度来看,我们的组件只是调用了 useState 和 useEffect,一个组件中可以调用多次useState和useEffect,它们都是完全独立的)
亲手实现一个自定义hook
实现useAxios发送异步请求
1.封装hook
- 使用useState定义参数
- 使用useEffect改变参数
import { useState, useEffect } from 'react';
import axios from 'axios';
// 封装axios ,发送自定义的网络请求hook
function useAxios(url) {
const [ loading, setLoading ] = useState(false);
const [ data, setData ] = useState()
const [ error, setError ] = useState()
useEffect(() => {
// 利用axios请求
setLoading(true)
axios.get(url)
.then(res => setData(res))
.catch(error => setError(error))
.finally(() => {setLoading(false)})
}, [url]) // 注意这里要传入参数url,代表url改变的时候才触发哦
return [loading, data, error] // 直接返回变量
}
export default useAxios;
2.使用hook
import React, { useState, useEffect } from 'react';
import useAxios from './UseAxios'; // 引入
export default () => {
const url = 'http://localhost:3000/';
// 数组解构,传入初始值
const [ loading, data, error ] = useAxios(url)
if (loading) {
return (<div>loading...</div>)
}
return error
? <div>{JSON.stringify(error)}</div>
: <div>{JSON.stringify(data)}</div>
}
显示结果:
然后我们再来模拟一下失败状态:
把url改成
const url = 'http://localhost:3000/abc';
实现useTitle,切换页面显示不同标题
对于不同的路由我们同样希望想多页应用一样能切换到对应的标题,这样可以让用户更好的知道页面的主题和内容,我是用在后台项目中,在封装好的headers组件中显示title,这里我们用网页标题来代替实现
定义hooks
import { useState, useEffect } from 'react';
// 封装axios ,发送自定义的网络请求hook
function useTitle(title) {
useEffect(() => {
document.title = title
}, [])
return;
}
export default useTitle;
使用hooks
import React, { useState, useEffect } from 'react';
import useTitle from './UseTitle'
export default () => {
useTitle('useTitle设置的标题33')
return <div>333</div>
}
然后再推荐两个已经封装好的自定义hook网站