而函数组件函数组件没有this,没有生命周期,没有状态state,函数的执行开销比创建类实例的开销要小。
因此,为了提高性能,尽量使用函数组件。
然而函数组件有个最大的问题就是没有状态state,所以react官方出了个hooks来解决这个问题。
项目中最常用的几个hook:
useState
1. useState最好写到函数的起始位置,便于阅读
2. useState严禁出现在代码块(判断、循环)中
3. useState返回的函数(数组的第二项),引用不变(节约内存空间)
4. 使用函数改变数据,若数据和之前的数据完全相等(使用Object.is比较),不会导致重新渲染,以达到优化效率的目的。
5. 使用函数改变数据,若传入的是值,只会保留最后一次的函数执行,若传入的是函数,会在事件完成后统一执行。
import React, { useState } from 'react';// 引入state hook
export default function App() {
console.log("App render")
const [n, setN] = useState(0); //使用一个状态,该状态的默认值是0
return <div>
<button onClick={() => {
setN(n - 1);
setN(n - 2);// 传入值,只会保留最后一次setN的执行
// setN(prevN => prevN - 1);
// setN(prevN => prevN - 1);//传入函数,在事件完成之后统一执行
}}>-</button>
<span>{n}</span>
6. 如果要实现强制刷新组件
类组件:使用forceUpdate函数
函数组件:使用一个空对象的useState
import React, { useState } from 'react'
export default function App() {
const [, forceUpdate] = useState({});
return <div>
<button onClick={() => {
forceUpdate({});
}}>强制刷新</button>
与类组件中componentDidMount和componentDidUpdate的区别
componentDidMount和componentDidUpdate,更改了真实DOM,但是用户还没有看到UI更新,是同步的。
useEffect中的副作用函数,更改了真实DOM,并且用户已经看到了UI更新,是异步的。
每个函数组件中,可以多次使用useEffect,但不要放入判断或循环等代码块中。
}, []);
//使用空数组作为依赖项,则副作用函数仅在挂载的时候运行
console.log("渲染组件"
);
const [, forceUpdate] =
useState({})
return <h1>Test组件 <button onClick={() =>
{
forceUpdate({})
}}>刷新组件</button></h1>
export default function App() {
const [visible, setVisible] = useState(
true)
return (
visible && <Test />
<button onClick={() =>
{
setVisible(!
visible);
}}>显示/隐藏</button>
useRef
useRef(value)返回一个对象:{current: value}
在每次渲染时返回同一个 ref 对象
变更 .current 属性不会引发组件重新渲染
import React, { useRef } from 'react'
export default function App() {
console.log('app render')
const nRef = useRef(10); // {current:10}
return (
<h1>{nRef.current}不会变</h1>
<button onClick={() => {nRef.current--;console.log(nRef.current, 'nRef.current变化')}}>减少</button>