Skip to content

Fix duplicate data in calendar and board#1105

Merged
hotlong merged 4 commits intomainfrom
copilot/fix-calendar-and-board-duplicate-data
Mar 21, 2026
Merged

Fix duplicate data in calendar and board#1105
hotlong merged 4 commits intomainfrom
copilot/fix-calendar-and-board-duplicate-data

Conversation

Copy link
Copy Markdown
Contributor

Copilot AI commented Mar 21, 2026

Fixes a bug where Calendar and Kanban views displayed every record twice.

Root Cause

When renderListView is provided (console app path), PluginObjectView was unconditionally fetching data in its own useEffect, even though the ListView (created by renderListView) independently fetches the same data. This caused:

  1. Two parallel fetch requests to the same endpoint
  2. PluginObjectView's state updates (setData, setLoading) triggering unnecessary re-renders
  3. These re-renders destabilizing the child component rendering pipeline, leading to duplicate records in Calendar and Kanban views

Additionally, ObjectKanban lacked proper external-data handling — it used fragile (props as any).data casting instead of explicit typed props, and didn't properly sync parent loading state changes.

Changes Made

Fix 1: packages/plugin-view/src/ObjectView.tsx

Skip PluginObjectView's data fetch when renderListView is provided, since the custom list view (e.g. ListView) handles its own data fetching.

Fix 2: packages/plugin-list/src/ListView.tsx

Added missing results.value (OData format) handling to the data extraction logic, consistent with extractRecords utility used elsewhere in the codebase.

Fix 3: packages/plugin-kanban/src/ObjectKanban.tsx

Added explicit data?: any[] and loading?: boolean props to ObjectKanbanProps interface. Implemented hasExternalData guard pattern (matching ObjectCalendar) that:

  • Detects when parent provides pre-fetched data via props
  • Skips internal dataSource.find() when external data is present
  • Syncs parent loading state changes via useEffect
  • Replaces fragile (props as any).data with typed destructured props

Regression Tests

  • DuplicateData.test.tsx: 3 tests verifying Calendar and Kanban views each render records exactly once (no duplicates), including wrapped response format
  • DataFetch.test.tsx: 1 new test for { value: [] } OData response format extraction

CHANGELOG.md

Updated with comprehensive description of all fixes.


✨ Let Copilot coding agent set things up for you — coding agent works faster and does higher quality work when set up for your repo.

@vercel
Copy link
Copy Markdown

vercel bot commented Mar 21, 2026

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated (UTC)
objectui-demo Ready Ready Preview, Comment Mar 21, 2026 0:39am
2 Skipped Deployments
Project Deployment Actions Updated (UTC)
objectui Ignored Ignored Mar 21, 2026 0:39am
objectui-storybook Ignored Ignored Mar 21, 2026 0:39am

Request Review

- Skip PluginObjectView data fetch when renderListView handles its own data,
  eliminating wasteful parallel fetches and re-renders that cause duplicate records
- Add results.value (OData format) handling to ListView data extraction

Co-authored-by: hotlong <50353452+hotlong@users.noreply.github.com>
Agent-Logs-Url: https://github.com/objectstack-ai/objectui/sessions/c52a20c8-22a2-4511-85ed-d8bc9fd98fdc
@hotlong
Copy link
Copy Markdown
Contributor

hotlong commented Mar 21, 2026

@copilot 继续

… tests

- ObjectKanban now accepts explicit `data` and `loading` props with
  `hasExternalData` guard (matching ObjectCalendar's pattern) to skip
  internal fetch when parent provides pre-fetched data
- Remove stale console.log in ObjectKanban
- Add OData `{ value: [] }` format test for ListView
- Add regression tests for duplicate data in Calendar and Kanban views
- Update CHANGELOG.md

Co-authored-by: hotlong <50353452+hotlong@users.noreply.github.com>
Agent-Logs-Url: https://github.com/objectstack-ai/objectui/sessions/7998282e-22f9-4b45-aca5-8f86440779c9
Copy link
Copy Markdown
Contributor Author

Copilot AI commented Mar 21, 2026

@copilot 继续

All remaining work items are now complete in commit af7a4a0:

Fix 3 — ObjectKanban external data handling: Added explicit data?: any[] and loading?: boolean props with hasExternalData guard pattern (matching ObjectCalendar). This replaces the fragile (props as any).data casting, properly skips internal fetch when parent provides data, and syncs loading state changes.

Regression tests: 4 new tests passing:

  • Calendar: no duplicate events (plain array + wrapped response format)
  • Kanban: no duplicate cards
  • ListView: OData { value: [] } extraction

CHANGELOG.md updated.

All 148+ existing tests continue to pass (128 kanban, 7 data fetch, 2 calendar nested config, 4 view switching, etc.).

Copilot AI changed the title [WIP] Fix duplicate data in calendar and board Fix duplicate data in calendar and board Mar 21, 2026
@hotlong hotlong marked this pull request as ready for review March 21, 2026 14:48
Copilot AI review requested due to automatic review settings March 21, 2026 14:48
@hotlong hotlong merged commit 94c94c1 into main Mar 21, 2026
6 checks passed
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR fixes duplicate record rendering in Calendar and Kanban views by eliminating unintended parallel data fetches when a custom renderListView is used (console path), and by improving consistency of record extraction across response shapes.

Changes:

  • Prevent @object-ui/plugin-view’s ObjectView from fetching its own data when renderListView is provided (avoids duplicate requests / re-render churn).
  • Extend @object-ui/plugin-list’s ListView to extract records from OData-style { value: [...] } responses and add a regression test.
  • Update @object-ui/plugin-kanban’s ObjectKanban to accept external data/loading props and skip internal fetching when external data is supplied; add console regression tests and update the changelog.

Reviewed changes

Copilot reviewed 6 out of 6 changed files in this pull request and generated 2 comments.

Show a summary per file
File Description
packages/plugin-view/src/ObjectView.tsx Skip internal fetch when renderListView is present to avoid duplicate requests and unstable downstream rendering.
packages/plugin-list/src/ListView.tsx Add { value: [] } response-shape extraction support.
packages/plugin-list/src/tests/DataFetch.test.tsx Add coverage for { value: [] } OData response extraction.
packages/plugin-kanban/src/ObjectKanban.tsx Add external data/loading props + guard to avoid double-fetch when parent supplies data.
apps/console/src/tests/DuplicateData.test.tsx Regression tests ensuring Calendar/Kanban render each record once.
CHANGELOG.md Document the fixes and associated tests.

loading: externalLoading,
onRowClick,
onCardClick,
...props
Copy link

Copilot AI Mar 21, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

...props is no longer used after removing the (props as any).data access. Consider removing the rest destructuring to avoid keeping an unused binding and to make it clear which props are supported/passed through.

Suggested change
...props

Copilot uses AI. Check for mistakes.
Comment on lines +54 to +58
useEffect(() => {
if (hasExternalData && externalLoading !== undefined) {
setLoading(externalLoading);
}
}, [externalLoading, hasExternalData]);
Copy link

Copilot AI Mar 21, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This useEffect updates the local loading state from the new loading prop, but loading is never used in the render output (not passed into KanbanRenderer and no loading UI is shown). Either wire loading through to the kanban renderer / show a loading skeleton/overlay, or remove the unused state+prop to avoid dead code.

Copilot uses AI. Check for mistakes.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants