跳到主要内容

Hooks 使用中的注意事项

几点注意事项

useState 初始化值,只有第一次有效

直接看代码

import {useState} from "react";

// 子组件
function Child({userInfo}) {
// render: 初始化 state
// re-render: 只恢复初始化的 state 值,不会再重新设置新的值
// 只能用 setName 修改
const [name, setName] = useState(userInfo.name)

return <div>
<p>child, props name:{userInfo.name}</p>
<p>child, state name:{name}</p>
</div>
}

function UseStateTrap() {
const [name, setName] = useState('lzw')
const userInfo = {name}

return <div>
<div>
parent &nbsp;
<button onClick={() => setName('张三')}>setName</button>
</div>ds
<Child userInfo={userInfo}/>
</div>
}

export default UseStateTrap

初始值

child, props name:lzw
child, state name:lzw

点击 setName 后结果

child, props name:张三
child, state name:lzw

useEffect 内部不能修改 state

直接看代码

import {useEffect, useState} from "react";

function UseEffectChangeState() {
const [count, setCount] = useState(0)

// 模拟 DidMount
useEffect(() => {
console.log('useEffect...', count)

// 定时任务
const timer = setInterval(() => {
console.log('setInterval...', count)
setCount(count + 1)
}, 1000)

// 清除定时任务
return () => clearInterval(timer)
}, []) // 依赖是 []

// 依赖是 [] 时: re-render 不会重新执行 effect 函数
// 没有依赖:re-render 会重新执行 effect 函数

return <div>count: {count}</div>
}

export default UseEffectChangeState

控制台输出

useEffect... 0
setInterval... 0

解决办法

import {useEffect, useState, useRef} from "react";

function UseEffectChangeState() {
const [count, setCount] = useState(0)

// 模拟 DidMount
let countRef = useRef(0)//解决办法
useEffect(() => {
console.log('useEffect...', count)

// 定时任务
const timer = setInterval(() => {
// console.log('setInterval...', count)
// setCount(count + 1)
//解决办法-----
console.log('setInterval...', countRef.current)
setCount(++countRef.current)
//解决办法-----
}, 1000)

// 清除定时任务
return () => clearInterval(timer)
}, []) // 依赖是 []

// 依赖是 [] 时: re-render 不会重新执行 effect 函数
// 没有依赖:re-render 会重新执行 effect 函数

return <div>count: {count}</div>
}

export default UseEffectChangeState

useEffect 可能出现死循环

死循环代码

import {useState, useEffect} from "react";
import axios from "axios";

// axios 返送网络请求
function useAxios(url, config = {}) {
const [loading, setLoading] = useState(false)
const [data, setData] = useState()
const [error, setError] = useState()

useEffect(() => {
// 利用 axios 发送网络请求
setLoading(true)
axios.get(url) // 发送一个 get 请求
.then(res => setData(res))
.catch(err => setError(err))
.finally(() => setLoading(false))
},
[url] // 只能使用值类型:a,b,c 这种,然后拼接成 const config = {a,b,c}
//[url,config] // 如果使用 config 对象,就回出现死循环
// 根本原因是 React 使用 Object.is 判断 依赖 是否变化
// Object.is(1,1) // true
// Object.is('a','a') // true
// Object.is({},{}) // false
// Object.is([],[]) // false
);

return [loading, data, error]
}

export default useAxios