react hooks将会是react未来的趋势。
开发环境搭建与示例编写
准备好,要开始咯!
开发环境搭建
React Hooks是React的新特性,不需要安装,只需要React版本在16.8以上,即可使用。
示例
首先编写一个小demo:
import React, { useState } from 'react';
export default function Example() {
const [ count, setCount ] = useState(0); // 数组解构
return (
<div>
<div>你已经点击了{count}次</div>
<button onClick={() => setCount(count + 1)}>点击</button>
</div>
)
}
注意:
useState
是一个方法,接收一个初始值。返回结果是一个数组:数组第一项是this.state
,第二项是this.setState
,在上面的例子里,只是给它们去了一个别名。
多状态声明
编写多个useState语句即可。
import React, { useState } from 'react';
export default function Example() {
const [name, setName] = useState('白山');
const [age, setAge] = useState(18);
return (
<div>
<div>{name}</div>
<div>{age}</div>
</div>
)
}
注意:useState
语句不能放在条件语句中。例如:
const isEmpty = true;
if (isEmpty) {
const [name, setName] = useState('白山');
}
使用useEffect代替生命周期
在react中,有各式各样的生命周期函数来辅助整个程序的运行。这些生命周期函数在Hooks可以使用useEffect进行替代。
代替componentDidMount
和componentDidUpdate
import React, { useState, useEffect } from 'react';
export default function Example() {
const [ count, setCount ] = useState(0); // 数组解构
useEffect(() => {
console.log(`done: ${count}`);
});
return (
<div>
<div>你已经点击了{count}次</div>
<button onClick={() => setCount(count + 1)}>点击</button>
</div>
)
}
注解:
useEffect
是一个函数,它的第一个参数是一个匿名函数
,useEffect触发时将会执行这个函数。
useEffect
的存在相当于componentDidMount
+componentDidUpdate
,React首次渲染和之后的每次渲染都会调用一遍useEffect
函数。
useEffect
不会阻碍视图的更新,因为它是异步的。
因为useEffect
是异步`的,所以它无法完成一些实时的操作。
比如,实时计算屏幕大小,调整页面布局,这个它是无法准确完成的,因为它异步的特性,会存在延时的情况。
🤗别着急,接着往下看👇👇👇
实现仅componentDidMount
上面的写法让它同时替代了两个生命周期函数,那如果我需要在首次渲染和重新渲染后执行不同的函数该怎么做呢?
首先,我们实现仅首次渲染后执行。这里需要介绍一下useEffect
的第二个参数,它的第二个参数是一个数组
。只有数组中的值发生变化了,才会调用 useEffect()
,而不是每次在渲染的时候调用。
当第二个参数为空数组([])的时候,代表不监听任何参数变化,即只有在组件初始化或销毁的时候才会触发,用来代替
componentDidMount
和componentWillUnmount
。
先来看一下如何实现componentDidMount
:
import React, { useState, useEffect } from 'react';
export default function Example() {
const [count, setCount] = useState(0); // 数组解构
useEffect(() => {
console.log('componentDidMount');
}, []);
return (
<div>
<div>你已经点击了{count}次</div>
<button onClick={() => setCount(count + 1)}>点击</button>
</div>
)
}
对比一下,就会发现仅仅只有一处地方修改了,那就是在useEffect
的第二个参数上加了一个空数组。
实现componentDidUpdate
例如我们监听一下变量count
的更新:
import React, { useState, useEffect } from 'react';
export default function Example() {
const [count, setCount] = useState(0); // 数组解构
useEffect(() => {
console.log('componentDidMount');
}, []);
useEffect(() => {
console.log(`componentDidUpdate: you click ${count} times`);
}, [count]);
return (
<div>
<div>你已经点击了{count}次</div>
<button onClick={() => setCount(count + 1)}>点击</button>
</div>
)
}
以上代码在执行的时候,第二个useEffect()
函数就相当于conponentDidUpdate
,首次渲染和变量count
更新时都会执行,因为首次渲染时,变量count
也被定义并被赋予初始值。
实现componentWillUnmount
以上介绍了如何使用useEffect实现首次加载的副作用和数据更新的副作用,而在实际的开发中,我们可能还需要在组件卸载时做一些操作。
这一点React Hooks也帮我们想到了。🤓
我们只需要在 useEffect() 中返回一个函数,就可以模拟
componentWillUnmount
的功能。
为了模拟卸载的状态,这里需要引入React Router用于路由的切换。
npm install --save react-router-dom
示例如下:
import React, { useState, useEffect } from 'react';
import { BrowserRouter as Router, Route, Link } from "react-router-dom"
export default function Example() {
const [count, setCount] = useState(0); // 数组解构
// useEffect(() => {
// console.log('componentDidMount');
// }, []);
// useEffect(() => {
// console.log(`componentDidUpdate: you click ${count} times`);
// }, [count]);
function Index() {
useEffect(() => {
console.log('老弟你来了 =》 index');
return () => {
// componentWillUnmount
console.log('老弟你走了 => index');
};
}, []);
return <h1>index</h1>;
}
function List() {
useEffect(() => {
console.log('老弟你来了 =》 list');
return () => {
// componentWillUnmount
console.log('老弟你走了 => list');
};
}, []);
return <h1>list</h1>;
}
return (
<div>
<div>你已经点击了{count}次</div>
<button onClick={() => setCount(count + 1)}>点击</button>
<Router>
<ul>
<li> <Link to="/">首页</Link> </li>
<li><Link to="/list/">列表</Link> </li>
</ul>
<Route path="/" exact component={Index} />
<Route path="/list/" component={List} />
</Router>
</div>
)
}
至此,componentWillUnmount
也就实现咯。
总结:
useEffect
其实等同于类组件的componentDidMount
、componentDidUpdate
和componentWillUnmount
的结合体 。