flushSync
console.log('runder');
const [num, setNum] = useState<number>(0);
const getLo = () => {
flushSync(() => {
setNum(111);
});
setNum(2222);
};
useState
const [num, setNum] = useState<number>(0);
useEffect
useEffect(() => {
const timer = setTimeout(() => {
setNum(1);
console.log(num);
}, 1000);
return () => {
clearTimeout(timer);
};
}, [num]);
useLayoutEffect
使用和useEffect几乎一样
区别在于:
首先要说明的是,useLayoutEffect和useEffect很像,函数签名也是一样。唯一的不同点就是useEffect是异步执行,而useLayoutEffect是同步执行的。 当函数组件刷新(渲染)时,包含useEffect的组件整个运行过程如下:
1. 触发组件重新渲染(通过改变组件state或者组件的父组件重新渲染,导致子节点渲染)。
1. 组件函数执行。
1. 组件渲染后呈现到屏幕上。
1. `useEffect` hook执行。
当函数组件刷新(渲染)时,包含useLayoutEffect的组件整个运行过程如下:
1. 触发组件重新渲染(通过改变组件state或者组件的父组件重新渲染,导致子组件渲染)。
1. 组件函数执行。
1. `useLayoutEffect` hook执行, React等待useLayoutEffect的函数执行完毕。
1. 组件渲染后呈现到屏幕上。
useEffect异步执行的优点是,react渲染组件不必等待useEffect函数执行完毕,造成阻塞。
ref
/*
React.createRef和useRef的区别
当函数组件更新时React.createRef会重新创建ref对象浪费性能,useRef会复用之前的
函数组件中用useref
类组件中使用React.createRef
当子组件是类组件时使用ref.currenth会获取到子组件实例所以可以拿到子组件的方法和state
*/
/**
* 方式一基于ref={函数}的方式可以把创建的dom元素赋值给变量(不推荐)
*/
let box
return <div ref={(x) => (box = x)}>Login</div>
/**
* 方式二 React.createRef 函数组件和类组件都可以用
*/
const box = React.createRef<HTMLDivElement>()
useEffect(() => {
console.log(box.current)
}, [])
return <div ref={box}>Login</div>
/**
* 方式三 useRef
*/
const box = useRef<HTMLDivElement>(null)
useEffect(() => {
console.log(box)
}, [])
return <div ref={box}>Login</div>
useRef获取子组件dom
interface ChildProps {}
const Child = forwardRef<HTMLDivElement, ChildProps>((props, ref) => {
return <div ref={ref} />;
});
useRef获取子组件方法及事件
interface ChildProps {}
interface ChildRef {
num: any;
setNum: any;
}
const Child = forwardRef<ChildRef, ChildProps>((props, ref) => {
const [num, setNum] = useState();
useImperativeHandle(ref, () => {
return {
num,
setNum,
};
});
return <div>111111</div>;
});
useMemo
const Demo = function Demo() {
let [supNum, setSupNum] = useState(10),
[oppNum, setOppNum] = useState(5),
[x, setX] = useState(0)
/*
let xxx = useMemo(callback,[dependencies])
+ 第一次渲染组件的时候,callback会执行
+ 后期只有依赖的状态值发生改变,callback才会再执行
+ 每一次会把callback执行的返回结果赋值给xxx
+ useMemo具备“计算缓存”,在依赖的状态值没有发生改变,callback没有触发执行的时候,xxx获取的是上一次计算出来的结果
和Vue中的计算属性非常的类似!!
+如果不使用useMemo的话ratio的计算逻辑每次组件更新都会执行
*/
let ratio = useMemo(() => {
let total = supNum + oppNum,
ratio = '--'
if (total > 0) ratio = (supNum / total * 100).toFixed(2) + '%'
return ratio
}, [supNum, oppNum])
return <div className="vote-box">
<div className="main">
<p>支持人数:{supNum}人</p>
<p>反对人数:{oppNum}人</p>
<p>支持比率:{ratio}</p>
<p>x:{x}</p>
</div>
<div className="footer">
<Button type="primary" onClick={() => setSupNum(supNum + 1)}>支持</Button>
<Button type="primary" danger onClick={() => setOppNum(oppNum + 1)}>反对</Button>
<Button onClick={() => setX(x + 1)}>干点别的事</Button>
</div>
</div>
}
useCallback +memo
const Child = React.memo(function Child(props) {
console.log('Child Render');
return <div>
我是子组件
</div>;
});
const Demo = function Demo() {
let [x, setX] = useState(0);
const handle = useCallback(() => { }, []);
return <div className="vote-box">
<Child handle={handle} />
<div className="main">
<p>{x}</p>
</div>
<div className="footer">
<Button type="primary" onClick={() => setX(x + 1)}>累加</Button>
</div>
</div>;
};
类组件
生命周期
class ExampleComponent extends react.Component {
constructor() {}
static getDerivedStateFromProps(nextProps, prevState) {
if (nextProps.riderId !== prevState.riderId) {
return {
riderId: nextProps.riderId
}
}
return null
}
shouldComponentUpdate(nextProps, nextState) {
return nextProps.id !== this.props.id
}
componentDidMount() {}
getSnapshotBeforeUpdate() {}
componentWillUnmount() {}
componentDidUnMount() {}
componentDidUpdate() {}
render() {}
UNSAFE_componentWillMount() {}
UNSAFE_componentWillUpdate(nextProps, nextState) {}
UNSAFE_componentWillReceiveProps(nextProps) {}
}