react hook的常用方法
useState、useEffect、useCallback、useMemo、useRef, 以及自定义hook
每个方法的如何使用?
以下方法说明及用例多自出自官方文档 传送门
useState
useState相当于class的state的赋值操作
import React, { useState } from 'react';
function Example() {
// 声明一个叫 "count" 的 state 变量
const [count, setCount] = useState(0);
return (
<div>
<p>You clicked {count} times</p>
<button onClick={() => setCount(count + 1)}>
Click me
</button>
</div>
);
}
// 等价于class的用法
class Example extends React.Component {
constructor(props) {
super(props);
this.state = {
count: 0
};
}
render() {
return (
<div>
<p>You clicked {this.state.count} times</p>
<button onClick={() => this.setState({ count: this.state.count + 1 })}>
Click me
</button>
</div>
);
}
}
useEffect
如果你熟悉 React class 的生命周期函数,你可以把 useEffect Hook 看做 componentDidMount,componentDidUpdate 和 componentWillUnmount 这三个函数的组合。
1.没有依赖变量的情况下
import React, { useState, useEffect } from 'react';
function Example() {
const [count, setCount] = useState(0);
useEffect(() => {
document.title = `You clicked ${count} times`;
return () => {
document.title = `leave current`;
};
}, []);
return (
<div>
<p>You clicked {count} times</p>
<button onClick={() => setCount(count + 1)}>
Click me
</button>
</div>
);
}
// class的形式
class Example extends React.Component {
constructor(props) {
super(props);
this.state = {
count: 0
};
}
componentDidMount() {
document.title = `You clicked ${this.state.count} times`;
}
componentDidUpdate() {
document.title = `You clicked ${this.state.count} times`;
}
componentWillUnmount{
document.title = `leave current`;
}
render() {
return (
<div>
<p>You clicked {this.state.count} times</p>
<button onClick={() => this.setState({ count: this.state.count + 1 })}>
Click me
</button>
</div>
);
}
}
2.依赖变量的情况下
// 对上面的例子做下修改,假设接受一个count变量
function Example({count}) {
useEffect(() => {
// 根据id获取商品详情的http请求等操作
return () => {
// 解耦操作防止内存泄漏
};
}, [count]);
return (
<div>
// something
</div>
);
}
useMemo
用于缓存计算结果。类似vue的计算属性,函数只依赖count的变化
import React, { useState, useMemo } from "react";
function Page() {
const [count, setCount] = useState(1);
const expensive = useMemo(() => {
console.log("compute");
let sum = 0;
for (let i = 0; i < count * 100; i += 1) {
sum += i;
}
return sum;
}, [count]);
return (
<div>
<h4>
{count}-{expensive}
</h4>
<div>
<button type="button" onClick={() => setCount(count + 1)}>
add
</button>
</div>
</div>
);
}
export default Page;
useCallback
useCallback(fn, deps) 相当于 useMemo(() => fn, deps)
import React, { useState, useCallback } from "react";
function Page() {
const [count, setCount] = useState(1);
function calculate(count) {
let sum = 0;
for (let i = 0; i < count * 100; i += 1) {
sum += i;
}
return sum;
}
const expensive = useCallback(calculate(count), [count]);
return (
<div>
<h4>
{count}-{calculate(count)}
</h4>
<div>
<button type="button" onClick={() => setCount(count + 1)}>
add
</button>
</div>
</div>
);
}
export default Page;
useRef
相当于class中的this
function TextInputWithFocusButton() {
const inputEl = useRef(null);
const onButtonClick = () => {
// `current` 指向已挂载到 DOM 上的文本输入元素
inputEl.current.focus();
};
useEffect(() => {
return () => {
console.log(inputEl.current);
inputEl.current = null;
console.log(inputEl.current);
};
})
return (
<>
<input ref={inputEl} type="text" />
<button onClick={onButtonClick}>Focus the input</button>
</>
);
}
自定义hook
它的名字应该始终以 use 开头,这样可以一眼看出其符合 Hook 的规则。 自定义hook在我理解的就是共享逻辑的封装,然后自定义hook不会共享 state,每一次引用都是完全独立的对象。return 一个对象或一个值。
下面为个简单的例子
// commonHook/index.js
import React, { useState, useEffect, useCallback } from "react";
function useWinSize() {
const [size, setSize] = useState({});
const onResize = useCallback(() => {
setSize({
width: document.documentElement.clientWidth,
height: document.documentElement.clientHeight,
});
}, []);
useEffect(() => {
window.addEventListener("resize", onResize);
return () => {
console.log("remove");
window.removeEventListener("resize", onResize);
};
}, []);
return size;
}
export default useWinSize;
// 在需要使用的地方
import React from "react";
import useWinSize from "../commonHook/index";
function Example() {
const size = useWinSize();
return (
<div>
自定义hook作为公共的逻辑处理,相当于一个函数,返回一个值或对象。
Page size: {size.width} * {size.height}
</div>
);
}
export default Example;