1.memo
其实react.memo的实现很简单,就几行代码。
export default function memo(
type: React$ElementType,
compare?: (oldProps: Props, newProps: Props) => boolean,
) {
if (__DEV__) {
if (!isValidElementType(type)) {
warningWithoutStack(
false,
'memo: The first argument must be a component. Instead ' +
'received: %s',
type === null ? 'null' : typeof type,
);
}
}
return {
$$typeof: REACT_MEMO_TYPE,
type,
compare: compare === undefined ? null : compare,
};
}
复制代码
可以看到,最终返回的是一个对象,这个对象带有一些标志属性,在react Fiber的过程中会做相应的处理。
在ReactFiberBeginWork.js中可以看到:
if (updateExpirationTime < renderExpirationTime) {
// This will be the props with resolved defaultProps,
// unlike current.memoizedProps which will be the unresolved ones.
const prevProps = currentChild.memoizedProps;
// Default to shallow comparison
let compare = Component.compare;
compare = compare !== null ? compare : shallowEqual;
if (compare(prevProps, nextProps) && current.ref === workInProgress.ref) {
return bailoutOnAlreadyFinishedWork(
current,
workInProgress,
renderExpirationTime,
);
}
}
复制代码
根据传入的compare
函数比较prevProps
和nextProps
,最终决定生成对象,并影响渲染效果。
其实在这之前,早已经有一个生命周期函数实现了相同的功能。他就是shouldComponentUpdate
。
之所以再增加这个memo
,也是react团队一直在秉承的信念。那就是让一切变得更加函数式
。
通过一个例子来看看memo如何使用。
先创建一个简单组件SubComponent
。
const SubComponent = props =>
<>
i am {props.name}. hi~
>
复制代码
调用React.memo创建memo组件
const Memo = React.memo(SubComponent, (prevProps, nextProps) =>
prevProps.name === nextProps.name
);
复制代码
在页面上调用memo
"App">
复制代码
memo
接收两个参数,一个是组件,一个是函数。这个函数就是定义了memo需不需要render的钩子。
比较前一次的props跟当前props,返回true表示不需要render。
也就是传给Memo的name不变时,不会触发SubComponent的render函数。
当前页面上的SubComponent还是之前的,并没有重新渲染。这也是为啥叫memo的原因吧。
2.lazy and suspence
React.lazy 用于做Code-Splitting
,代码拆分。类似于按需加载,渲染的时候才加载代码。
用法如下:
import React, {lazy} from 'react';
const OtherComponent = lazy(() => import('./OtherComponent'));
function MyComponent() {
return (
);
}
复制代码
lazy(() => import('./OtherComponent'))
使用es6的import()返回一个promise,类似于:
lazy(() => new Promise(resolve =>
setTimeout(() =>
resolve(
// 模拟ES Module
{
// 模拟export default
default: function render() {
return Other Component
}
}
),
3000
)
));
复制代码
React.lazy的提出是一种更优雅的条件渲染解决方案。
之所以说他更优雅,是因为他将条件渲染的优化提升到了框架层。
这里我们引出suspense。
当我们组件未渲染完成,需要loading时,可以这么写:
const OtherComponent = React.lazy(() => import('./OtherComponent'));
function MyComponent() {
return (
Loading... }>