react相关hooks(二)

2023-12-15 05:14:12

不写性能优化的时候

const Child = (props) => {
	console.log(child function is recalled)// count1改变时多次执行
	return (
		<div>
			<h1>{ props.count2}</h1>
		</div>
	)
}
function app () {
	const [count1.setCount1] = useState(0)
	const [count2.setCount2] = useState(0)
	return (
		<div>
			<h1>count1:{count1}</h1>
			<button onClick={()=> setCount1(count1+1)}>+</button>
			<Child count2={count2}/>
			<button onClick={()=> setCount2(count2+1)}>+</button>
		</div>
	)
}
root.render(<App />)

memo

const Child = memo((props) => {
	console.log(child function is recalled)// count1改变时不会多次执行
	return (
		<div>
			<h1>{ props.count2}</h1>
		</div>
	)
})
/**
 * 
 * 函数组件最大的弱点:渲染执行
 * 当一个组建的状态发生了改变的时候 相关视图是必然要更新的
 * 函数组件在视图更新的需求来临的时候 函数是必然要执行的
 */
function app () {
	const [count1.setCount1] = useState(0)
	const [count2.setCount2] = useState(0)
	return (
		<div>
			<h1>count1:{count1}</h1>
			<button onClick={()=> setCount1(count1+1)}>+</button>
			<Child count2={count2}/>
			<button onClick={()=> setCount2(count2+1)}>+</button>
		</div>
	)
}
root.render(<App />)

useMemo

/**
 *  memo会对引用进行比较,这种比较时浅比较,
 * 	如果更新了一个新的引用,那么child就会被执行
 *  count1更新 app重新执行 child 必然要重新赋值一个新引用
 */
const Child = memo((props) => {
	console.log(child function is recalled)// count1改变时会多次执行
	return (
		<div>
			<h1>{ props.childData.count2}</h1>
		</div>
	)
})
function app () {
	const [count1.setCount1] = useState(0)
	const [count2.setCount2] = useState(0)
	const childData = {
		count2
	}
	return (
		<div>
			<h1>count1:{count1}</h1>
			<button onClick={()=> setCount1(count1+1)}>+</button>
			<Child childData={childData}/>
			<button onClick={()=> setCount2(count2+1)}>+</button>
		</div>
	)
}

const Child = memo(props) => {
	console.log(child function is recalled)// count1改变时不会多次执行
	return (
		<div>
			<h1>{ props.childData.count2}</h1>
		</div>
	)
}
function app () {
	const [count1.setCount1] = useState(0)
	const [count2.setCount2] = useState(0)
	// const childData = {
	// 	count2
	// }
	// 只有依赖变了才会返回新的引用
	// 不是为了子组件/返回常量的时候,不需要使用useMemo
	const childData = useMemo(() => ({count2}),[count2])
	/**
	 * const newCount1 = useMemo(()=>count1*2,[count1])
	 * 类似vue计算属性 可以使用useMemo
	 */
	return (
		<div>
			<h1>count1:{count1}</h1>
			<button onClick={()=> setCount1(count1+1)}>+</button>
			<Child childData={childData}/>
			<button onClick={()=> setCount2(count2+1)}>+</button>
		</div>
	)
}

useCallback

const Child = memo(props) => {
	console.log(child function is recalled)// count1改变时会多次执行
	return (
		<div>
			<h1>{props.childData.count2}</h1>
			<button onClick={props.setCount2}>+</button>
			
		</div>
	)
}

function app () {
	const [count1.setCount1] = useState(0)
	const [count2.setCount2] = useState(0)
	const cbSetCount2 = () => {
		() => setCount2(count2 + 1);
	}
	return (
		<div>
			<h1>count1:{count1}</h1>
			<button onClick={()=> setCount1(count1+1)}>+</button>
			<Child childData={childData} setCount2={cbSetCount2 } />
		</div>
	)
}
const Child = memo(props) => {
	console.log(child function is recalled)// count1改变时不会多次执行
	return (
		<div>
			<h1>{props.childData.count2}</h1>
			<button onClick={props.setCount2}>+</button>
			
		</div>
	)
}

function app () {
	const [count1.setCount1] = useState(0)
	const [count2.setCount2] = useState(0)
	// 函数是静态的 一般情况下是不会增加依赖的 除非是用户配置 比如面向对象 在this上增加函数 prototype上增加函数
	const cbSetCount2 = useCallback(() => {
		() => setCount2(count2 + 1);
	},[])
	return (
		<div>
			<h1>count1:{count1}</h1>
			<button onClick={()=> setCount1(count1+1)}>+</button>
			<Child childData={childData} setCount2={cbSetCount2 } />
		</div>
	)
}

memo手写

const { component } = React;
export default class PureComponent extends Component {
	// 如果你需要自定义shouldComponentUpdate 那么就不能继承pureComponent(pureComponent字段该函数)
	// 该函数无法鉴定动态的变化
	shouldComponentUpdate (nextProps, nextState) { 
		return !shallowEqual(this.props,nextProps) ||!shallowEqual(this.state,nextState)
	}
}

function shallowEqual (o1, o2) {
	// 组件不能调用render函数
	if (o1 === o2) return true;
	if (typeof o1 !== 'object' || o1 === null || typeof o2 !== 'object' || o2 === null) {
		return false;
	}
	const k1 = Object.keys(o1);
	const k2 = Object.keys(o2);

	if (k1.length !== k2.length) return false;
	
	for (const k of k1) {
		if (!o2.hasOwnProperty(k) || o1[k] !== o2[k]) {
			return false;
		}
	}
	return true;
}
export function memo (Fc) {
	return class extends PureComponent{
		return () {
			return Fc(this.props)
		}
	}
}
useMemo
function useMemo(cb,depArr){
	if (memoArr[memoIndex]) {
		const [_memo, _dep] = memoArr[memoIndex]
		const isFullySame = depArr.every((dep, index) => dep === _dep[index]);
		if (isFullySame) { 
			memoIndex++;
			return _memo;
		} else {
			return setNewMemo(cb,depArr)
		}
	} else {
		return setNewMemo(cb,depArr)
	}
	function setNewMemo (cb, depArr) {
		const memo = cb();
		memoArr[memoIndex++] = [memo, depArr]
		return memo;
	}
}

useCallback
function useCallback(cb,depArr){
	if (callbackArr[callbackIndex]) {
		const [_callback, _dep] = callbackArr[callbackIndex]
		const isFullySame = depArr.every((dep, index) => dep === _dep[index]);
		if (isFullySame) { 
			callbackIndex++;
			return _callback;
		} else {
			return setNewCallback(cb,depArr)
		}
	} else {
		return setNewCallback(cb,depArr)
	}
	function setNewCallback (cb, depArr) {
		callbackArr[callbackIndex++] = [cb,depArr]
	}
}

文章来源:https://blog.csdn.net/qq_41662017/article/details/134792061
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。