Remove UNSAFE_componentWillReceiveProps from JSONTree

Update JSONTree to a functional component to remove the unsave receive props. The
functional component uses a useMemo hook on the theme to avoid creating the theme style
unless the theme has changed.
This commit is contained in:
Roman Shtylman 2022-01-23 11:40:29 -08:00
parent b992fcc653
commit f70f18364d

View File

@ -3,13 +3,12 @@
// Dave Vedder <veddermatic@gmail.com> http://www.eskimospy.com/ // Dave Vedder <veddermatic@gmail.com> http://www.eskimospy.com/
// port by Daniele Zannotti http://www.github.com/dzannotti <dzannotti@me.com> // port by Daniele Zannotti http://www.github.com/dzannotti <dzannotti@me.com>
import React from 'react'; import React, { useMemo } from 'react';
import PropTypes from 'prop-types'; import PropTypes from 'prop-types';
import JSONNode from './JSONNode'; import JSONNode from './JSONNode';
import createStylingFromTheme from './createStylingFromTheme'; import createStylingFromTheme from './createStylingFromTheme';
import { import {
invertTheme, invertTheme,
StylingConfig,
StylingFunction, StylingFunction,
StylingValue, StylingValue,
Theme, Theme,
@ -47,63 +46,47 @@ const defaultLabelRenderer = ([label]: (string | number)[]) => (
); );
const noCustomNode = () => false; const noCustomNode = () => false;
function checkLegacyTheming(theme: Theme | undefined, props: Props) { export function JSONTree(props: Props) {
const deprecatedStylingMethodsMap = { const {
getArrowStyle: 'arrow', data: value,
getListStyle: 'nestedNodeChildren', keyPath = ['root'],
getItemStringStyle: 'nestedNodeItemString', postprocessValue = identity,
getLabelStyle: 'label', hideRoot = false,
getValueStyle: 'valueText', theme,
}; invertTheme: invertThemeProp,
shouldExpandNode = expandRootNode,
getItemString = defaultItemString,
labelRenderer = defaultLabelRenderer,
valueRenderer = identity,
isCustomNode = noCustomNode,
collectionLimit = 50,
} = props;
const deprecatedStylingMethods = Object.keys( const styling = useMemo(() => {
deprecatedStylingMethodsMap const finalTheme = invertThemeProp ? invertTheme(theme) : theme;
).filter((name) => props[name as keyof Props]); return createStylingFromTheme(finalTheme);
}, [theme, invertThemeProp]);
if (deprecatedStylingMethods.length > 0) { return (
if (typeof theme === 'string') { <ul {...styling('tree')}>
theme = { <JSONNode
extend: theme, postprocessValue={postprocessValue}
}; hideRoot={hideRoot}
} else { styling={styling}
theme = { ...theme }; shouldExpandNode={shouldExpandNode}
} getItemString={getItemString}
labelRenderer={labelRenderer}
deprecatedStylingMethods.forEach((name) => { valueRenderer={valueRenderer}
// eslint-disable-next-line no-console isCustomNode={isCustomNode}
console.error( collectionLimit={collectionLimit}
`Styling method "${name}" is deprecated, use "theme" property instead` keyPath={hideRoot ? [] : keyPath}
value={postprocessValue(value)}
/>
</ul>
); );
(theme as StylingConfig)[
deprecatedStylingMethodsMap[
name as keyof typeof deprecatedStylingMethodsMap
]
] = ({ style }, ...args) => ({
style: {
...style,
...props[name as keyof Props](...args),
},
});
});
} }
return theme; JSONTree.propTypes = {
}
function getStateFromProps(props: Props) {
let theme = checkLegacyTheming(props.theme, props);
if (props.invertTheme) {
theme = invertTheme(theme);
}
return {
styling: createStylingFromTheme(theme),
};
}
export class JSONTree extends React.Component<Props, State> {
static propTypes = {
data: PropTypes.any, data: PropTypes.any,
hideRoot: PropTypes.bool, hideRoot: PropTypes.bool,
theme: PropTypes.oneOfType([PropTypes.object, PropTypes.string]), theme: PropTypes.oneOfType([PropTypes.object, PropTypes.string]),
@ -115,65 +98,4 @@ export class JSONTree extends React.Component<Props, State> {
sortObjectKeys: PropTypes.oneOfType([PropTypes.func, PropTypes.bool]), sortObjectKeys: PropTypes.oneOfType([PropTypes.func, PropTypes.bool]),
}; };
static defaultProps = {
shouldExpandNode: expandRootNode,
hideRoot: false,
keyPath: ['root'],
getItemString: defaultItemString,
labelRenderer: defaultLabelRenderer,
valueRenderer: identity,
postprocessValue: identity,
isCustomNode: noCustomNode,
collectionLimit: 50,
invertTheme: true,
};
constructor(props: Props) {
super(props);
this.state = getStateFromProps(props);
}
UNSAFE_componentWillReceiveProps(nextProps: Props) {
if (
['theme', 'invertTheme'].find(
(k) => nextProps[k as keyof Props] !== this.props[k as keyof Props]
)
) {
this.setState(getStateFromProps(nextProps));
}
}
shouldComponentUpdate(nextProps: Props) {
return !!Object.keys(nextProps).find((k) =>
k === 'keyPath'
? nextProps[k].join('/') !== this.props[k].join('/')
: nextProps[k as keyof Props] !== this.props[k as keyof Props]
);
}
render() {
const {
data: value,
keyPath,
postprocessValue,
hideRoot,
theme, // eslint-disable-line no-unused-vars
invertTheme: _, // eslint-disable-line no-unused-vars
...rest
} = this.props;
const { styling } = this.state;
return (
<ul {...styling('tree')}>
<JSONNode
{...{ postprocessValue, hideRoot, styling, ...rest }}
keyPath={hideRoot ? [] : keyPath}
value={postprocessValue(value)}
/>
</ul>
);
}
}
export { StylingValue }; export { StylingValue };