import React, { useState, useEffect, useRef } from "react";
/**
* react运行机制:
* useState和useEffect,都是在页面render的时候生成了本次render的state,function,effects
* 所以页面每次有更新,都会执行effect方法
* 如果后面跟的是一个空数组,只会在第一次执行的时候调用。这样以后render的时候,都不会生成新的effects
* 这样可能会导致,拿到的state不是最新的state
* 如果要拿到最新的state,可以在数组后面监听某个值的变化,从而再去做effect的事情,保证这次的render是
* state的更新,拿到最新的一份state的数据。
* */
/**
* useRef
* 1、保存全局的一个状态,这样就不会导致状态的一个丢失,拿到的永远是最新一次render的状态。
* 2、可以获取到dom的节点,调用方法。
* **/
const LikeButton: React.FC = () => {
const [count, setCount] = useState(0);
const [on, setOn] = useState(false);
const [pos, setPos] = useState({ x: 0, y: 0 });
const countRef = useRef(0);
const inputRef = useRef<HTMLInputElement>(null);
useEffect(() => { // 不传参的情况下,每次页面有更新都会执行一次
document.title = `tap ${count} num`;
}, [count])
useEffect(() => { // react 在执行这次effect的时候,会把上次的effect清除
console.log(' addEventListener')
const changePos = (e: MouseEvent) => {
setPos({ x: e.clientX, y: e.clientY })
}
// console.log(' addEventListener', pos);
document.addEventListener('click', changePos);
return () => {
// 会在下一次执行上面 addEventListener 方法的时候,回调这个removeEventListener
// 先把上次的状态清除
// console.log(' removeEventListener', pos);
document.removeEventListener('click', changePos);
}
}, []);
return (
<>
<div onClick={() => {
setCount(count + 1);
countRef.current = (count + 1);
if (inputRef.current) {
inputRef.current.focus();
}
}}>相加<span>{count}</span></div>
<div onClick={() => {
console.log(' == 延迟3秒获取state , 点击这个按钮,然后狂点相加的时候,alert弹出的count只会是点击按钮那一刻的count ==');
setTimeout(()=>{
alert(count);
console.log(' === ref ==', countRef.current);
}, 3000)
}}>延迟3秒去获取状态的具体值</div>
<div onClick={() => { setOn(!on) }}>{on ? 'on' : 'off'}</div>
<div>posX{pos.x} === posY{pos.y}</div>
<input ref={inputRef} />
</>
)
}
export default LikeButton;
自定义hooks
import { useEffect, useState } from "react";
/**
* 自定义hooks
* 但是这些hooks都是相互隔离的,A页面的pos和B页面的pos的数据是指向的不同内存
* 虽然显示的数据是一样的,但是实际的内存指向都是不一样的
* */
const useMousePostion = () => {
const [pos, setPost] = useState({ x: 0, y: 0 });
useEffect(()=>{
const handleMove = (e: MouseEvent) => {
setPost({ x: e.clientX, y: e.clientY });
}
document.addEventListener('mousemove', handleMove);
return () => {
document.removeEventListener('mousemove', handleMove);
}
}, [])
return pos;
}
export default useMousePostion;
const pos = useMousePostion();