From 5175bc0a00e07fa78d87d59b386e2fa5b35395b9 Mon Sep 17 00:00:00 2001 From: Nathan Bierema Date: Tue, 3 Jan 2023 09:05:13 -0500 Subject: [PATCH] shouldExpandNode => shouldExpandNodeInitially --- .../react-json-tree/src/JSONIterableNode.tsx | 1 + .../react-json-tree/src/JSONNestedNode.tsx | 192 +++++++----------- packages/react-json-tree/src/index.tsx | 9 +- packages/react-json-tree/src/types.ts | 4 +- 4 files changed, 83 insertions(+), 123 deletions(-) diff --git a/packages/react-json-tree/src/JSONIterableNode.tsx b/packages/react-json-tree/src/JSONIterableNode.tsx index 98d7671f..ad24d5f5 100644 --- a/packages/react-json-tree/src/JSONIterableNode.tsx +++ b/packages/react-json-tree/src/JSONIterableNode.tsx @@ -35,6 +35,7 @@ const JSONIterableNode: React.FunctionComponent = ({ ...props }) => { nodeType="Iterable" nodeTypeIndicator="()" createItemString={createItemString} + expandable /> ); }; diff --git a/packages/react-json-tree/src/JSONNestedNode.tsx b/packages/react-json-tree/src/JSONNestedNode.tsx index 38a67373..7f47f8db 100644 --- a/packages/react-json-tree/src/JSONNestedNode.tsx +++ b/packages/react-json-tree/src/JSONNestedNode.tsx @@ -1,4 +1,4 @@ -import React from 'react'; +import React, { useCallback, useState } from 'react'; import JSONArrow from './JSONArrow'; import getCollectionEntries from './getCollectionEntries'; import JSONNode from './JSONNode'; @@ -91,128 +91,86 @@ interface Props extends CommonInternalProps { nodeTypeIndicator: string; createItemString: (data: any, collectionLimit: number) => string; expandable: boolean; - circularCache: CircularCache; - level: number; } -interface State { - expanded: boolean; -} +export default function JSONNestedNode(props: Props) { + const { + circularCache = [], + collectionLimit, + createItemString, + data, + expandable, + getItemString, + hideRoot, + isCircular, + keyPath, + labelRenderer, + level = 0, + nodeType, + nodeTypeIndicator, + shouldExpandNodeInitially, + styling, + } = props; -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, - }; -} + const [expanded, setExpanded] = useState( + // calculate individual node expansion if necessary + isCircular ? false : shouldExpandNodeInitially(keyPath, data, level) + ); -export default class JSONNestedNode extends React.Component { - static defaultProps = { - data: [], - circularCache: [], - level: 0, - expandable: true, - }; + const handleClick = useCallback(() => { + if (expandable) setExpanded(!expanded); + }, [expandable, expanded]); - constructor(props: Props) { - super(props); - this.state = getStateFromProps(props); - } + const renderedChildren = + expanded || (hideRoot && level === 0) + ? renderChildNodes({ ...props, circularCache, level: level + 1 }) + : null; - UNSAFE_componentWillReceiveProps(nextProps: Props) { - const nextState = getStateFromProps(nextProps); - if (getStateFromProps(this.props).expanded !== nextState.expanded) { - this.setState(nextState); - } - } + const itemType = ( + + {nodeTypeIndicator} + + ); + const renderedItemString = getItemString( + nodeType, + data, + itemType, + createItemString(data, collectionLimit), + keyPath + ); + const stylingArgs = [keyPath, nodeType, expanded, expandable] as const; - 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 { - getItemString, - nodeTypeIndicator, - nodeType, - data, - hideRoot, - createItemString, - styling, - collectionLimit, - keyPath, - labelRenderer, - expandable, - } = this.props; - const { expanded } = this.state; - const renderedChildren = - expanded || (hideRoot && this.props.level === 0) - ? renderChildNodes({ ...this.props, level: this.props.level + 1 }) - : null; - - const itemType = ( - - {nodeTypeIndicator} + return hideRoot ? ( +
  • +
      + {renderedChildren} +
    +
  • + ) : ( +
  • + {expandable && ( + + )} + + + {renderedItemString} - ); - const renderedItemString = getItemString( - nodeType, - data, - itemType, - createItemString(data, collectionLimit), - keyPath - ); - const stylingArgs = [keyPath, nodeType, expanded, expandable] as const; - - return hideRoot ? ( -
  • -
      - {renderedChildren} -
    -
  • - ) : ( -
  • - {expandable && ( - - )} - - - {renderedItemString} - -
      - {renderedChildren} -
    -
  • - ); - } - - handleClick = () => { - if (this.props.expandable) { - this.setState({ expanded: !this.state.expanded }); - } - }; +
      + {renderedChildren} +
    + + ); } diff --git a/packages/react-json-tree/src/index.tsx b/packages/react-json-tree/src/index.tsx index ea3e668f..286ec76f 100644 --- a/packages/react-json-tree/src/index.tsx +++ b/packages/react-json-tree/src/index.tsx @@ -13,7 +13,7 @@ import type { GetItemString, IsCustomNode, LabelRenderer, - ShouldExpandNode, + ShouldExpandNodeInitially, } from './types'; interface Props extends Partial { @@ -23,7 +23,8 @@ interface Props extends Partial { } 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) => ( {itemType} {itemString} @@ -39,7 +40,7 @@ export function JSONTree({ keyPath = ['root'], labelRenderer = defaultLabelRenderer, valueRenderer = identity, - shouldExpandNode = expandRootNode, + shouldExpandNodeInitially = expandRootNode, hideRoot = false, getItemString = defaultItemString, postprocessValue = identity, @@ -62,7 +63,7 @@ export function JSONTree({ styling={styling} labelRenderer={labelRenderer} valueRenderer={valueRenderer} - shouldExpandNode={shouldExpandNode} + shouldExpandNodeInitially={shouldExpandNodeInitially} hideRoot={hideRoot} getItemString={getItemString} postprocessValue={postprocessValue} diff --git a/packages/react-json-tree/src/types.ts b/packages/react-json-tree/src/types.ts index 7bb4297b..bcccc597 100644 --- a/packages/react-json-tree/src/types.ts +++ b/packages/react-json-tree/src/types.ts @@ -26,7 +26,7 @@ export type ValueRenderer = ( ...keyPath: KeyPath ) => React.ReactNode; -export type ShouldExpandNode = ( +export type ShouldExpandNodeInitially = ( keyPath: KeyPath, data: any, level: number @@ -46,7 +46,7 @@ export interface CommonExternalProps { keyPath: KeyPath; labelRenderer: LabelRenderer; valueRenderer: ValueRenderer; - shouldExpandNode: ShouldExpandNode; + shouldExpandNodeInitially: ShouldExpandNodeInitially; hideRoot: boolean; getItemString: GetItemString; postprocessValue: PostprocessValue;