mirror of
https://github.com/wassname/talk.git
synced 2026-07-25 13:30:59 +08:00
Optimize Slot rendering
This commit is contained in:
@@ -4,19 +4,48 @@ import styles from './Slot.css';
|
||||
import {connect} from 'react-redux';
|
||||
import {getSlotElements} from 'coral-framework/helpers/plugins';
|
||||
import omit from 'lodash/omit';
|
||||
import union from 'lodash/union';
|
||||
import isEqual from 'lodash/isEqual';
|
||||
|
||||
function Slot ({fill, inline = false, className, reduxState, defaultComponent: DefaultComponent, ...rest}) {
|
||||
let children = getSlotElements(fill, reduxState, rest);
|
||||
const pluginConfig = reduxState.config.pluginConfig || {};
|
||||
if (children.length === 0 && DefaultComponent) {
|
||||
children = <DefaultComponent {...rest} />;
|
||||
class Slot extends React.Component {
|
||||
shouldComponentUpdate(next) {
|
||||
|
||||
// Prevent Slot from rerendering when only reduxState has changed and
|
||||
// it does not result in a change of slot children.
|
||||
const keys = union(Object.keys(this.props), Object.keys(next));
|
||||
const changes = keys.filter((key) => this.props[key] !== next[key]);
|
||||
if (changes.length === 1 && changes[0] === 'reduxState') {
|
||||
const prevChildrenUuid = this.getChildren(this.props).map((child) => child.type.talkUuid);
|
||||
const nextChildrenUuid = this.getChildren(next).map((child) => child.type.talkUuid);
|
||||
return !isEqual(prevChildrenUuid, nextChildrenUuid);
|
||||
}
|
||||
|
||||
// Prevent Slot from rerendering when no props has shallowly changed.
|
||||
return changes.length !== 0;
|
||||
}
|
||||
|
||||
return (
|
||||
<div className={cn({[styles.inline]: inline, [styles.debug]: pluginConfig.debug}, className)}>
|
||||
{children}
|
||||
</div>
|
||||
);
|
||||
getSlotProps({fill: _a, inline: _b, className: _c, reduxState: _d, defaultComponent_: _e, ...rest} = this.props) {
|
||||
return rest;
|
||||
}
|
||||
|
||||
getChildren(props = this.props) {
|
||||
return getSlotElements(props.fill, props.reduxState, this.getSlotProps(props));
|
||||
}
|
||||
|
||||
render() {
|
||||
const {inline = false, className, reduxState, defaultComponent: DefaultComponent} = this.props;
|
||||
let children = this.getChildren();
|
||||
const pluginConfig = reduxState.config.pluginConfig || {};
|
||||
if (children.length === 0 && DefaultComponent) {
|
||||
children = <DefaultComponent {...this.getSlotProps(this.props)} />;
|
||||
}
|
||||
|
||||
return (
|
||||
<div className={cn({[styles.inline]: inline, [styles.debug]: pluginConfig.debug}, className)}>
|
||||
{children}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
Slot.propTypes = {
|
||||
|
||||
@@ -9,6 +9,7 @@ import {loadTranslations} from 'coral-framework/services/i18n';
|
||||
import {injectReducers} from 'coral-framework/services/store';
|
||||
import camelize from './camelize';
|
||||
import plugins from 'pluginsConfig';
|
||||
import uuid from 'uuid/v4';
|
||||
|
||||
export function getSlotComponents(slot, reduxState, props = {}) {
|
||||
const pluginConfig = reduxState.config.plugin_config || {};
|
||||
@@ -100,7 +101,12 @@ function addMetaDataToSlotComponents() {
|
||||
const slots = plugin.module.slots;
|
||||
slots && Object.keys(slots).forEach((slot) => {
|
||||
slots[slot].forEach((component) => {
|
||||
|
||||
// Attach plugin name to the component
|
||||
component.talkPluginName = plugin.name;
|
||||
|
||||
// Attach uuid to the component
|
||||
component.talkUuid = uuid();
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user