1.state hook : set同一变量的话不重新render
import React, { useState } from 'react';
export default function Test() {
const [count, setCount] = useState({ c: 0 });
const add = () => {
console.log('count', count);
setCount({ ...count, c: count.c + 1 }); // 方式1
// setCount(Object.assign(count, { c: count.c + 1 })); // 方式2
};
return (
<div>
<button onClick={add}>加一加一</button>
<div>{count.c}</div>
</div>
);
}
- 方式1:点击按钮,正常渲染,div里面的数值加1,打印出的count里面的c值也加1
- 方式2:点击按钮,不渲染,div里面的数值不变,打印出的count里面的c值却是加1了。
- 总结:state hook设置值,如果值不变(Object.assign返回的是目标对象,也就是第一个参数,因此前后对象地址不变)是不触发重新渲染的,但是值是设置进去了
2.effect hook : 监听变化对象
import React, { useState } from 'react';
import Child from './Child.js';
export default function Test() {
const [number, setNumber] = useState({ n: 0 });
const [total, setTotal] = useState(0);
const cut = () => {
setNumber({ ...number, n: number.n - 1 });
};
const obj = {};
return (
<div>
<button onClick={cut}>减一减一</button> //操作1
<button onClick={() => setTotal(prev => prev + 1)}>addTotal</button> //操作2
<div>{number.n}</div>
<Child count={number}></Child> // 情况1
<Child count={{ ...number }}></Child> // 情况2
<Child count={Object.assign(obj, number)}></Child> // 情况3
<Child count={obj}></Child> // 情况4
<Child count={{}}></Child> // 情况5
</div>
);
}
// Child.js
import React, { useEffect } from 'react';
export default function Child({ count }) {
useEffect(() => {
console.log('count', count);
}, [count]);
return <div>888</div>;
}
__结果:
- 操作1: 以上5种情况,子组件里面的count都变化了,说明传入进来的对象的地址每次都不一样。每次render时Test函数都会执行一遍,也就是会进行一次render。情况1之所以变化了是因为修改的正是子组件监听的值
- 操作2:情况2,3,4,5子组件里面count变化了,情况1并没有变化,说明其他值(total)导致的render不会影响其他state中的对象(number)变化。
3.effect hook : 监听不变化对象
import React, { useState } from 'react';
import Child from './Child.js';
const obj2 = {};
export default function Test() {
const [number, setNumber] = useState({ n: 0 });
const cut = () => {
setNumber({ ...number, n: number.n - 1 });
};
return (
<div>
<button onClick={cut}>减一减一</button>
<div>{number.n}</div>
<Child count={obj2}></Child> // 情况1
<Child count={Object.assign(obj2, number)}></Child> // 情况2
</div>
);
}
// Child.js
import React, { useEffect } from 'react';
export default function Child({ count }) {
useEffect(() => {
console.log('count', count);
}, [count]);
return <div>888</div>;
}
结果:以上情况,子组件里面的count都未变化,说明传入进来的对象的地址每次都一样。因为变量是在函数外面定义的,每次render时执行Test函数,并不会重新定义变量。