Skip to content

Expansion state is lost when src prop updates to an object missing a previously expanded path. #72

@regeter

Description

@regeter

Expansion state is lost when src prop updates to an object missing a previously expanded path.

Description:
The component's internal expansion state is destructively modified when the src prop is updated. If a previously expanded path does not exist in the new src object, that path is permanently removed from the expansion state. This causes a poor user experience when navigating between objects that have slightly different data structures, as the user's manual expansions are lost.

Steps to Reproduce:

  1. Render the JsonView component with an initial src object, for example:
    { "request": { "header": { "id": "123" } }, "other_data": {} }
  2. Manually expand the request node, and then expand the nested header node.
  3. Update the component by passing a new src prop that is missing the header node, for example:
    { "request": { "body": { "id": "456" } }, "other_data": {} }
  4. Update the component again by passing the original src prop from step 1.

Actual Behavior:
In step 4, the header node is rendered as collapsed. The user's interaction state from step 2 has been lost.

Expected Behavior:
The component's internal expansion state should be preserved across src updates. In step 4, the header node should be rendered as expanded, just as the user left it in step 2. The absence of a path in one src object should not purge that path's state for subsequent re-renders.

Suggested Fix / Architectural Analysis:

The root cause of this issue is the decentralized state management for collapsed nodes.

In src/components/object-node.tsx, the collapse state for each individual object/array is managed by a local useState hook:

// in src/components/object-node.tsx
const [fold, _setFold] = useState(isCollapsed(...))

Because this state is local to each ObjectNode instance, it is destroyed when that component unmounts. When the src prop of the main JsonView component is updated with an object that has a different structure, the old component instances are unmounted, and their local state is permanently lost.

A more robust architectural solution would be to centralize the expansion state.

The expansion state for the entire tree could be managed within the top-level JsonView component (src/components/json-view.tsx). This could be a single state object that maps node paths to their collapsed status (e.g., collapsedPaths: { 'request.header': false }).

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions