Hooks 使用中的注意事项
几点注意事项
useState 初始化值,只有第一次有效
直接看代码
js
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
<button onClick={() => setName('张三')}>setName</button>
</div>
ds
<Child userInfo={userInfo} />
</div>
);
}
export default UseStateTrap;
初始值
js
child, props name:lzw
child, state name:lzw
点击 setName 后结果
js
child, props name:张三
child, state name:lzw
useEffect 内部不能修改 state
直接看代码
js
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;
控制台输出
js
useEffect... 0
setInterval... 0
解决办法
js
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 可能出现死循环
死循环代码
js
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;