案例7:
useLayoutEffect: 与useEffect 作用基本相同 控制函数组件生命周期
useLayoutEffect: 执行的时间是在 挂载之前、更新之前 执行
useLayoutEffect(() => {
挂载之前、更新之前执行的业务代码
return () => {
销毁之前执行的业务代码
};
}, [依赖项列表])
Father.jsx:
import {useState, useEffect, useLayoutEffect} from 'react'
useEffect(() => {
let start = new Date().getTime();
// 死循环 造成JS 代码线程阻塞
while(true){
let end = new Date().getTime();
// 如果 超过 2秒中退出循环
if(end-start >= 1000){
break;
}
if(num === 0){
setnum(Math.random()); //仅使用测试使用
console.log('setCount...............num:', num);
}
}
}, [num]);*/
useLayoutEffect(() => {
let start = new Date().getTime();
// 死循环 造成JS 代码线程阻塞
while(true){
let end = new Date().getTime();
// 如果 超过 2秒中退出循环
if(end-start >= 1000 ){
break;
}
if(num === 0){
setnum(Math.random());
console.log('setCount...............num:', num);
}
}
},[num]);
return (
<div>
<h1>Father组件: useLayoutEffect</h1>
<h3 className='h3 text-danger'>num: {num}</h3>
<button onClick={handleNum}>num随机值</button>
</div>
)
}
export default Father
案例八:
useRef : 在函数组件中 创建一个 ref 对象
useImperativeHandle: 在函数组件中将组件内部的属性(变量、状态、 方法) 暴露给直系父组件
注: 要配合 forwardRef 函数使用
useImperativeHandle(
函数组件捆绑的ref变量名,
() => {
return {
将函数组件内暴露的属性写在返回值对象中
}
},
[依赖项列表],
)
Father.jsx:
import {useRef} from 'react';
import Son from './Son';
const Father = () => {
// 创建一个 ref
const SonRef = useRef();
const handleRef = e => {
console.log('SonRef=>', SonRef);
SonRef.current.sonupdateTitle(e);
}
return (
<div >
<h1>Father组件: useRef</h1>
<button onClick={handleRef}>useRef</button>
<hr/>
<Son ref={SonRef}/>
</div>
)
}
export default Father
Son.jsx:
import {useState, memo, forwardRef, useImperativeHandle} from 'react'
const Son = (props, sonRef) => {
const [title, settitle] = useState('Hello Son');
useImperativeHandle(
sonRef,
() => ({
sonStateTitle: title,
sonupdateTitle: updateTitle
}),
[title],
)
const updateTitle = e => {
settitle(new Date().getTime())
}
return (
<div>
<h1>Son组件</h1>
<h3>title:{title}</h3>
<button onClick={updateTitle}>修改title</button>
</div>
)
}
export default memo(forwardRef(Son));
案例九:
useMemo 与 useCallback : 缓存结果
useMemo: 相当于 vue 中计算属性(computed), 缓存计算结果值
let computedResult = useMemo(
() => {
return 计算结果(任意类型)
},
[依赖项列表]
);
computedResult: 返回值 useMemo 函数计算的结果值
依赖项列表: 依赖项列表中任意的一个只发生改变 则会重新执行 useMemo 函数中中第一个参数(函数对象/重新计算)
useCallback: 缓存一个函数对象
let computedFunction = useCallback(
() => {
业务代码
},
[依赖项],
)
computedFunction 返回值 : 函数对象类型 就是useCallback函数中的第一个参数对象
useCallback(fn, deps) 相当于 useMemo(() => fn, deps)。
Father.jsx:
import {useState, useMemo} from 'react'
const Father = () => {
const [msg, setMsg] = useState('Hello');
let computedResult = useMemo(
() => {
console.log('useMemo执行..............');
return msg+' '+'abc';
},
[msg]
);
const handleMsg = e=> {
setMsg(new Date().getTime());
}
return (
<div>
<h1>Father组件: useMemo</h1>
<h3>msg: {msg}</h3>
<h3>useMemo1: {computedResult}</h3>
<h3>useMemo2: {computedResult}</h3>
<h3>useMemo3: {computedResult}</h3>
<button onClick={handleMsg}>msg</button>
</div>
)
}
export default Father
Father1.jsx:
import {useState,useCallback, useEffect} from 'react'
const Father1 = () => {
const [slot, setslot] = useState(()=>(<h1>初始Slot</h1>));
const [count, setcount] = useState(0)
let computedFunction = useCallback(
() => {
return (<h3>useCallback Hook函数 {count}</h3>)
},
[]
)
useEffect(() => {
console.log('执行useEffect........');
}, [computedFunction])
const changSlot = ()=>{
let temp = computedFunction();
setslot(temp);
}
return (
<div>
<h1>Father1组件: useCallback</h1>
<h3>count:{count}</h3>
<button onClick={changSlot}>点击</button>
<button onClick={e=>setcount(count+1)}>修改count值</button>
<hr/>
<div>
slot:{slot}
</div>
</div>
)
}
export default Father1
案例十
Father.jsx
import { useReducer } from 'react';
import reducer from './reducer';
/*
useReducer
*/
const mystate = { count: 0 };
const Father = () => {
const [state, dispatch] = useReducer(reducer, mystate);
const add = num => {
dispatch({type: 'add', count: 1});
}
const minus = num => {
dispatch({type: 'minus', count: 1});
}
return (
<div>
<h1>Father组件: useReducer</h1>
<h3>count: {state.count}</h3>
<button onClick={e=>add(1)}>+1</button>
<button onClick={e=>minus(1)}>-1</button>
</div>
)
}
export default Father
recuder.js
const reducer = (state, action) => {
switch (action.type) {
case 'add':
return {...state, count: state.count + action.count};
case 'minus':
return {...state, count: state.count - action.count};
default:
return state;
}
}
export default reducer;