ReactHook新特性
...
ReactHook新特性
Hook与stateHook
在之前的函数组件中,只能放纯视图而不能放业务进去:
export default function StateHook() {
return (
<div>StateHookDemo</div>
)
}
StateHook形式可以让函数组件也拥有state:
import { useState } from 'react';
export default function StateHook() {
const [ message, setMessage ] = useState('StateHookDemo');
return (
<div>{ message }</div>
)
}
如果想要用事件修改state值,需要回调一个传统方式定义的函数,并用set函数修改,直接传递要改成的值:
function handleClick() {
setMessage('new StateHookDemo')
}
return (
<div>
<p>{ message }</p>
<button onClick={ handleClick }>Change text</button>
</div>
)
EffectHook
基本使用
这东西相当于componentDidMount
,componentDidUpdate
和 componentWillUnmount
三个生命周期钩子的组合,在不同场景下是不同的生命周期钩子。
这个例子中它是componentDidMount
,一开始就执行更改标签题目:
export default function EffectHookDemo() {
useEffect(() => {
console.log('execute automaticlly');
})
return (
<div>
<p>Effect Hook Demo</p>
</div>
)
}
当它内部有涉及状态修改的操作时,相当于componentDidUpdate
:
export default function EffectHookDemo() {
const [ count, setcount ] = useState(0);
useEffect(() => {
document.title = `${ count }`;
})
function handleAdd() {
setcount(count+1);
}
return (
<div>
<p>Effect Hook Demo</p>
<button onClick={ handleAdd }>Add</button>
</div>
)
}
而且,useEffect钩子是可以写很多个的,当必要时它们都会执行而不会被最后一个覆盖:
useEffect(() => {
document.title = `${ count }`;
});
useEffect(() => {
log('execute Automatically');
});
因此它能做到业务分离,不需要把所有逻辑全挤在一个钩子里。
状态监听参数
默认状态下,useEffect会监听所有状态的修改,只要有state被改了它就执行。如果想指定监听某几个state,就加一个数组形式的参数:
useEffect(() => {
log('execute Automatically');
}, []);
如果为空,就谁也不监听,只在Mounted执行一次。
EffectHook副作用
假设有如下的一个定时器:
const MyAPI = {
count: 0,
subscribe(cb) {
this.intervalId = setInterval(() => {
this.count += 1;
cb(this.count);
}, 1000)
},
unsubscribe() {
clearInterval(this.intervalId);
this.reset();
},
reset() {
this.count = 0;
}
}
调用subscribe时传入一个函数,每隔一秒执行一次,且参数+1。在组件的useEffect里这样调:
const [ count, setCount ] = useState(0);
useEffect(() => {
MyAPI.subscribe(count => {
setCount(count);
});
});
return (
<div>
<p>{ count }</p>
</div>
)
会发现执行出来效果及其鬼畜,会瞬间增大到一个巨大的值。这是因为,每当count被修改,useEffect就要重新执行一次,相当于每次的执行次数都会翻倍。不能直接把useEffect当做一个简单的回调函数用。正确用法是像刚才说的那样加个空监听参数,把它彻底变成componentDidMount。
由于在组件中设置了定时器,那当然需要在销毁时一起清除:
useEffect(() => {
MyAPI.subScribe(count => {
setCount(count)
});
return function() {
MyAPI.unsubscribe();
}
}, []);
useEffect的返回值函数就相当于componentWillUnmount。