Use compose to combine React components
react-components-compose
Read this in other languages: 简体中文
Use compose to combine React components, which is convenient to combine and replace React components.
Installation
npm install react-components-compose
or
yarn add react-components-compose
Usage
Simple component display
The outer middle and inner will be shown below
import reactComponentsCompose from 'react-components-compose'
const Outer = (props) => {
// children points to the child nodes of the current react element
const { children } = props;
return <>
<div>outer</div>
{children}
</>
}
const Middle: React.FC<any> = (props) => {
const { children } = props;
return <>
<div>middle</div>
{children}
</>
}
const Inner: React.FC<any> = (props) => {
const { children } = props;
return <>
<div>inner</div>
</>
}
export const SimpleShow = () => {
const components = [Outer, Middle, Inner]
return (
<div>
{reactComponentsCompose(components)}
</div>
);
};
Adjust props
import { reactComponentsCompose } from "react-components-compose";
const Outer = (props) => {
const { children, data } = props;
// show outer 123
return (
<>
<div>outer {data}</div>
{children}
</>
);
};
const Middle = (props) => {
const { children } = props;
// Pass in additional props via cloneElement
return (
<>
<div>middle</div>
{React.cloneElement(children, { data: 789 })}
</>
);
};
const Inner = (props) => {
const { data } = props;
// The obtained data is 789, showing inner 789
return (
<>
<div>inner {data}</div>
</>
);
};
export const SimpleShowWithProps = () => {
// Pass component props in turn
const components = [[Outer, {data: 123}], Middle, [Inner, {data: 456}]];
return (
<div>
{reactComponentsCompose(components)}
</div>
);
};
Add event notification
import { reactComponentsCompose } from "react-components-compose";
import mitt from "mitt";
// No other functions, only responsible for event clearing
const EventClear = (props) => {
const { children, bus } = props;
// Used to clear the data in the bus
React.useEffect(() => {
return () => {
bus.all.clear();
};
}, []);
return (
<>
{React.cloneElement(children, { bus })}
</>
);
};
class OuterClass extends React.Component<any, any> {
constructor(props) {
super(props);
this.state = {
time: 0,
};
}
handleClick = () => {
// Trigger out click with parameter 123
this.props.bus.emit("out click", 123);
};
render(): React.ReactNode {
const { data, bus, children } = this.props;
return (
<>
{data}
<div onClick={this.handleClick}>outer</div>
{React.cloneElement(children as React.ReactElement, { bus })}
</>
);
}
}
const Inner = (props) => {
const { data, bus } = props;
const [time, setTime] = React.useState(0);
React.useEffect(() => {
// * means to listen to all events, type is the event name, params is the event value
bus.on("*", (type, params) => {
console.log(type, params);
alert(params);
});
}, []);
const handleClick = () => {
setTime(time + 1);
};
return [
<div>{time} {data}</div>,
<div onClick={handleClick}>inner</div>,
<div>inner2</div>,
<div>inner3</div>,
];
};
export const ArrayShowWithEvent1 = () => {
const components = [[EventClear, {bus: mitt()}], OuterClass, [Inner, {data: times}]];
return (
<div>
{reactComponentsCompose(components)}
</div>
);
};
// Consider not clearing mitt processing, for components, there are "global" variables
export const ArrayShowWithEvent3 = () => {
const bus = mitt();
// Clear mitt event binding can be written here
const components = [
[OuterClass, { bus }],
[Inner, { data: "times", bus }],
];
return (
<div>
{reactComponentsCompose(components)}
</div>
);
};