如何使用多版本的React
在开发过程中使用联邦模块功能,使用其他项目的React组件,会出现 Minified React error #321; 错误。这是由于多个版本的React导致的。
在React@17中,事件系统进行了更改。这可以让我们使用React的多版本,解决多个版本的React导致的错误。
导出组件出口
我们创建一个函数,来包裹我们需要导出的组件出口。
import type { FunctionComponent, ComponentClass } from 'react';
import { render, unmountComponentAtNode } from 'react-dom';
interface CreateLegacyRoot {
render(props: any): void;
unmount(): void;
}
type LegacyReturn = (container: HTMLElement) => CreateLegacyRoot;
/**
* 创建一个createLegacyRoot函数,保证组件能够兼容多个react版本
* @param { FunctionComponent | ComponentClass } Component - 组件
*/
function legacy(Component: FunctionComponent | ComponentClass): LegacyReturn {
return function createLegacyRoot(container: HTMLElement): CreateLegacyRoot {
return {
render(props: any): void {
render(<Component { ...props } />, container);
},
unmount(): void {
unmountComponentAtNode(container);
}
};
};
}
export default legacy;
然后导出一个方法,供其他位置调用。
export const createLegacyRoot = legacy(Component);
在其他项目调用方法
我们创建一个Loader函数,来加载导出的方法。
import { useRef, useEffect } from 'react';
/**
* 加载联邦模块
* @param { Function } props.loader - 加载的联邦模块
* @param { object } props.moduleProps
*/
function Loader(props) {
const { loader, moduleProps } = props;
const containerRef = useRef(), // dom,ReactDOM.render渲染的节点
rootRef = useRef(); // 保存root对象
// 加载并渲染模块
async function loadModule() {
const { createLegacyRoot } = await loader();
rootRef.current = createLegacyRoot(containerRef.current);
rootRef.current.render(moduleProps);
}
useEffect(function() {
loadModule();
return function() {
rootRef.current.unmount();
};
}, [loader, moduleProps]);
return <div ref={ containerRef } />;
}
export default Loader;
然后加载组件并调用。
function App(props) {
function handleClick(event) {
alert('你点击了按钮。');
}
return (
<div>
<Loader loader={ () => import('project/module') }
moduleProps={{ onClick: handleClick }}
/>
</div>
);
}