shouldExpandNode => shouldExpandNodeInitially

This commit is contained in:
Nathan Bierema 2023-01-03 09:05:13 -05:00
parent 9c4307780f
commit 5175bc0a00
4 changed files with 83 additions and 123 deletions

View File

@ -35,6 +35,7 @@ const JSONIterableNode: React.FunctionComponent<Props> = ({ ...props }) => {
nodeType="Iterable" nodeType="Iterable"
nodeTypeIndicator="()" nodeTypeIndicator="()"
createItemString={createItemString} createItemString={createItemString}
expandable
/> />
); );
}; };

View File

@ -1,4 +1,4 @@
import React from 'react'; import React, { useCallback, useState } from 'react';
import JSONArrow from './JSONArrow'; import JSONArrow from './JSONArrow';
import getCollectionEntries from './getCollectionEntries'; import getCollectionEntries from './getCollectionEntries';
import JSONNode from './JSONNode'; import JSONNode from './JSONNode';
@ -91,74 +91,39 @@ interface Props extends CommonInternalProps {
nodeTypeIndicator: string; nodeTypeIndicator: string;
createItemString: (data: any, collectionLimit: number) => string; createItemString: (data: any, collectionLimit: number) => string;
expandable: boolean; expandable: boolean;
circularCache: CircularCache;
level: number;
} }
interface State { export default function JSONNestedNode(props: Props) {
expanded: boolean;
}
function getStateFromProps(props: Props) {
// calculate individual node expansion if necessary
const expanded = !props.isCircular
? props.shouldExpandNode(props.keyPath, props.data, props.level)
: false;
return {
expanded,
};
}
export default class JSONNestedNode extends React.Component<Props, State> {
static defaultProps = {
data: [],
circularCache: [],
level: 0,
expandable: true,
};
constructor(props: Props) {
super(props);
this.state = getStateFromProps(props);
}
UNSAFE_componentWillReceiveProps(nextProps: Props) {
const nextState = getStateFromProps(nextProps);
if (getStateFromProps(this.props).expanded !== nextState.expanded) {
this.setState(nextState);
}
}
shouldComponentUpdate(nextProps: Props, nextState: State) {
return (
!!Object.keys(nextProps).find(
(key) =>
key !== 'circularCache' &&
(key === 'keyPath'
? nextProps[key].join('/') !== this.props[key].join('/')
: nextProps[key as keyof Props] !== this.props[key as keyof Props])
) || nextState.expanded !== this.state.expanded
);
}
render() {
const { const {
getItemString, circularCache = [],
nodeTypeIndicator,
nodeType,
data,
hideRoot,
createItemString,
styling,
collectionLimit, collectionLimit,
createItemString,
data,
expandable,
getItemString,
hideRoot,
isCircular,
keyPath, keyPath,
labelRenderer, labelRenderer,
expandable, level = 0,
} = this.props; nodeType,
const { expanded } = this.state; nodeTypeIndicator,
shouldExpandNodeInitially,
styling,
} = props;
const [expanded, setExpanded] = useState<boolean>(
// calculate individual node expansion if necessary
isCircular ? false : shouldExpandNodeInitially(keyPath, data, level)
);
const handleClick = useCallback(() => {
if (expandable) setExpanded(!expanded);
}, [expandable, expanded]);
const renderedChildren = const renderedChildren =
expanded || (hideRoot && this.props.level === 0) expanded || (hideRoot && level === 0)
? renderChildNodes({ ...this.props, level: this.props.level + 1 }) ? renderChildNodes({ ...props, circularCache, level: level + 1 })
: null; : null;
const itemType = ( const itemType = (
@ -188,18 +153,18 @@ export default class JSONNestedNode extends React.Component<Props, State> {
styling={styling} styling={styling}
nodeType={nodeType} nodeType={nodeType}
expanded={expanded} expanded={expanded}
onClick={this.handleClick} onClick={handleClick}
/> />
)} )}
<label <label
{...styling(['label', 'nestedNodeLabel'], ...stylingArgs)} {...styling(['label', 'nestedNodeLabel'], ...stylingArgs)}
onClick={this.handleClick} onClick={handleClick}
> >
{labelRenderer(...stylingArgs)} {labelRenderer(...stylingArgs)}
</label> </label>
<span <span
{...styling('nestedNodeItemString', ...stylingArgs)} {...styling('nestedNodeItemString', ...stylingArgs)}
onClick={this.handleClick} onClick={handleClick}
> >
{renderedItemString} {renderedItemString}
</span> </span>
@ -208,11 +173,4 @@ export default class JSONNestedNode extends React.Component<Props, State> {
</ul> </ul>
</li> </li>
); );
}
handleClick = () => {
if (this.props.expandable) {
this.setState({ expanded: !this.state.expanded });
}
};
} }

View File

@ -13,7 +13,7 @@ import type {
GetItemString, GetItemString,
IsCustomNode, IsCustomNode,
LabelRenderer, LabelRenderer,
ShouldExpandNode, ShouldExpandNodeInitially,
} from './types'; } from './types';
interface Props extends Partial<CommonExternalProps> { interface Props extends Partial<CommonExternalProps> {
@ -23,7 +23,8 @@ interface Props extends Partial<CommonExternalProps> {
} }
const identity = (value: any) => value; const identity = (value: any) => value;
const expandRootNode: ShouldExpandNode = (keyPath, data, level) => level === 0; const expandRootNode: ShouldExpandNodeInitially = (keyPath, data, level) =>
level === 0;
const defaultItemString: GetItemString = (type, data, itemType, itemString) => ( const defaultItemString: GetItemString = (type, data, itemType, itemString) => (
<span> <span>
{itemType} {itemString} {itemType} {itemString}
@ -39,7 +40,7 @@ export function JSONTree({
keyPath = ['root'], keyPath = ['root'],
labelRenderer = defaultLabelRenderer, labelRenderer = defaultLabelRenderer,
valueRenderer = identity, valueRenderer = identity,
shouldExpandNode = expandRootNode, shouldExpandNodeInitially = expandRootNode,
hideRoot = false, hideRoot = false,
getItemString = defaultItemString, getItemString = defaultItemString,
postprocessValue = identity, postprocessValue = identity,
@ -62,7 +63,7 @@ export function JSONTree({
styling={styling} styling={styling}
labelRenderer={labelRenderer} labelRenderer={labelRenderer}
valueRenderer={valueRenderer} valueRenderer={valueRenderer}
shouldExpandNode={shouldExpandNode} shouldExpandNodeInitially={shouldExpandNodeInitially}
hideRoot={hideRoot} hideRoot={hideRoot}
getItemString={getItemString} getItemString={getItemString}
postprocessValue={postprocessValue} postprocessValue={postprocessValue}

View File

@ -26,7 +26,7 @@ export type ValueRenderer = (
...keyPath: KeyPath ...keyPath: KeyPath
) => React.ReactNode; ) => React.ReactNode;
export type ShouldExpandNode = ( export type ShouldExpandNodeInitially = (
keyPath: KeyPath, keyPath: KeyPath,
data: any, data: any,
level: number level: number
@ -46,7 +46,7 @@ export interface CommonExternalProps {
keyPath: KeyPath; keyPath: KeyPath;
labelRenderer: LabelRenderer; labelRenderer: LabelRenderer;
valueRenderer: ValueRenderer; valueRenderer: ValueRenderer;
shouldExpandNode: ShouldExpandNode; shouldExpandNodeInitially: ShouldExpandNodeInitially;
hideRoot: boolean; hideRoot: boolean;
getItemString: GetItemString; getItemString: GetItemString;
postprocessValue: PostprocessValue; postprocessValue: PostprocessValue;