Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Conversation

@pipewrk
Copy link
Contributor

@pipewrk pipewrk commented Oct 7, 2025

Summary

Release 0.3.0: React Hooks Migration to UI Package & Resource API Refinements

Sprint: 5 (Bindings & Interactivity) + Bug fixes
Scope: resource · ui · e2e-utils

Links

Why

The original PR #71 successfully moved React hooks from @geekist/wp-kernel to @geekist/wp-kernel-ui, but introduced a critical bug in the refactored loading state logic. This PR completes the release with the following fixes:

  1. Loading State Bug: The refactored computeListState function was creating new objects on every call, breaking useSelect's referential equality checks and causing infinite loading states
  2. Grouped API Cleanup: Removed the redundant use.* namespace from grouped API (keeping direct useGet/useList as preferred thin-flat API)
  3. Documentation Updates: Updated all docs to reflect that hooks come from @geekist/wp-kernel-ui

What

  • ✅ Fixed resource hook loading state logic to trust store status over resolution flags
  • ✅ Removed use.* grouped API namespace (redundant with thin-flat useGet/useList)
  • ✅ Updated resource-hooks.ts to return primitives from helper functions (proper memoization)
  • ✅ Fixed shouldShowLoadingState to not check hasFinishedResolution when status is already resolved
  • ✅ Updated documentation across kernel and UI packages
  • ✅ All E2E tests passing

How

Loading State Fix:
The bug was in shouldShowLoadingState - it checked hasFinishedResolution === false even when status === 'success'. WordPress's data store has a quirk where hasFinishedResolution can return false even after status is success.

Solution: Trust the explicit status value ('success' or 'error') and only check hasFinishedResolution when status is 'idle'.

Refactoring Fix:
Changed helper functions to return primitives (booleans) instead of objects, allowing useSelect to properly memoize the final object created in the callback.

Trade-offs:

  • Removed use.* grouped API - developers should use resource.useGet() instead of resource.use.item()
  • Added debug logging (to be removed in future cleanup)

Testing

How to verify locally:

  1. pnpm install && pnpm build
  2. pnpm wp:start
  3. Navigate to Jobs admin page
  4. Expected: Jobs list loads without infinite loading spinner
  5. Search for "Nonexistent role"
  6. Expected: Empty state appears (no loading spinner)

Test Matrix

  • Unit (pnpm test) - 969 passed, 2 skipped
  • E2E (pnpm e2e) - All passing including "renders jobs and supports search filtering"
  • Types (pnpm typecheck) - Clean
  • Types Tests (pnpm typecheck:tests) - Clean
  • WordPress playground / wp-env - Manually verified

Screenshots / Recordings

Loading state now resolves correctly when data is available.

Breaking Changes

  • None for runtime (hooks still work the same way)
  • Dev-facing: Removed resource.use.item() and resource.use.list() from grouped API
    • Migration: Use resource.useGet() and resource.useList() instead (thin-flat API)

Affected Packages

  • @geekist/wp-kernel - Removed use grouped API namespace
  • @geekist/wp-kernel-ui - Fixed resource hooks loading logic
  • @geekist/wp-kernel-cli
  • @geekist/wp-kernel-e2e-utils

Release

  • minor — feature sprint + critical fixes (0.3.0)

CHANGELOG.md updated in kernel and ui packages with:

  • Removed use.* grouped API namespace
  • Fixed resource hook loading state bug
  • Updated docs to reflect UI package hooks

Checklist

  • Tests pass (pnpm test) - 969 passed
  • E2E pass (pnpm e2e) - All scenarios passing
  • Lint passes (pnpm lint)
  • Types pass (pnpm typecheck, pnpm typecheck:tests)
  • CHANGELOG.md updated in affected packages
  • Docs updated (kernel.md, resources.md, resources-advanced.md)
  • Examples updated (documentation shows thin-flat API pattern)

Note: This PR represents the complete 0.3.0 release that was partially merged in #71. The commit history includes the original migration work plus critical bug fixes discovered during integration testing.

Sprint 5: Move hooks to @geekist/wp-kernel-ui

This release completes the separation of React-specific code from the core
kernel package, moving all hooks to @geekist/wp-kernel-ui while maintaining
backward compatibility through runtime attachment.

## Breaking Changes
- Removed `use` namespace from ResourceObject grouped API (use thin-flat API instead)
- React hooks (useGet, useList, useAction, usePolicy, etc.) now require @geekist/wp-kernel-ui

## Features
- Added React hooks package (@geekist/wp-kernel-ui) with full test coverage
- Hooks attach to resources at runtime via globalThis bridge
- New hooks: useAction, usePolicy, useHoverPrefetch, useVisiblePrefetch, useNextPagePrefetch
- Enhanced prefetching capabilities with intersection observer support

## Bug Fixes
- Fixed useSelect referential equality issue causing infinite re-renders
- Fixed loading state logic: trust status='success' over hasFinishedResolution
- Removed React code from kernel package (now framework-agnostic)
- Updated resource hooks to use primitive returns for proper memoization

## Documentation
- Added comprehensive guides for all new hooks
- Updated API documentation with hook examples
- Added prefetching guide with real-world patterns
- Updated resource guides to reflect UI package integration

## Improvements
- Refactored high-complexity functions with helper utilities
- Added ESLint rules for code quality enforcement
- Improved test coverage across all packages
- Enhanced JSDoc comments throughout codebase

## Related
- Closes #71
- Major milestone toward beta release

Co-authored-by: Release Please <[email protected]>
Copilot AI review requested due to automatic review settings October 7, 2025 17:59
@pipewrk pipewrk added the codex label Oct 7, 2025
Copy link
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

Completes 0.3.0 release: fixes resource hook loading-state regression after moving React hooks into UI package, removes deprecated grouped use.* API in favor of thin-flat useGet / useList, and refactors validation, namespace detection, store reducer, and transport/event emission for clarity and modularity.

  • Fixes infinite loading by trusting list status over hasFinishedResolution and memoizing hook selector results.
  • Removes grouped resource.use.item()/list() API and updates docs/tests; broad type refactors (interfaces → type aliases) plus internal decomposition of large functions (namespace detection, policy/cache, actions).
  • Adds stricter lint rules & supporting dev deps; augments tests for loading edge cases.

Reviewed Changes

Copilot reviewed 53 out of 107 changed files in this pull request and generated 3 comments.

Show a summary per file
File Description
packages/ui/src/hooks/usePolicy.ts Reordered conditional to equivalent positive form for policy runtime presence.
packages/ui/src/hooks/useAction.ts Refactored dispatch resolution into smaller helpers (env check, registry, store registration, invoke wrapper).
packages/ui/src/hooks/resource-hooks.ts Centralized loading logic into helper functions; simplified selector return objects.
packages/ui/src/hooks/internal/useStableCallback.ts Expanded internal documentation for hook utilities.
packages/ui/src/hooks/tests/resource-hooks.test.ts Added tests covering new loading-state semantics (idle unresolved, resolving after success).
packages/kernel/src/resource/validation.ts Modularized config validation with reusable helpers and shared constants.
packages/kernel/src/resource/types.ts Converted many interfaces to type aliases; removed grouped use hook namespace.
packages/kernel/src/resource/store.ts Refactored reducer into discrete pure helpers with action handler map.
packages/kernel/src/resource/grouped-api.ts Removed createUseGetter (deprecated grouped hooks).
packages/kernel/src/resource/define.ts Removed grouped use getter; minor window access simplifications.
packages/kernel/src/resource/cache.ts Interface → type alias changes and invalidate options alias.
packages/kernel/src/resource/tests/* Updated tests removing grouped use expectations.
packages/kernel/src/reporter/types.ts Interfaces → type aliases for reporter contracts.
packages/kernel/src/policy/* Refactors: split emission paths (hooks, broadcast, bridge), granular cache broadcast message types.
packages/kernel/src/namespace/detect.ts Large refactor: decomposed detection pipeline, candidate evaluation; added helpers & internal docs.
packages/kernel/src/namespace/tests/detect.test.ts Adjusted test expectations for new fallback sanitization behavior.
packages/kernel/src/http/* Introduced helper emit functions; refactored api-fetch resolution and event emission.
packages/kernel/src/error/* Interfaces → type aliases.
packages/kernel/src/data/plugins/events.ts Type alias conversions and middleware typing tweak.
packages/kernel/src/actions/* Type alias conversions; refactored lifecycle emission into smaller functions.
packages/e2e-utils/src/types.ts Interfaces → type aliases for test utilities.
packages/e2e-utils/src/createKernelUtils.ts Added secure selector parsing & path extraction for store helpers.
packages/e2e-utils/src/tests/createStoreHelper.test.ts Updated tests to reflect restricted selector capability.
app/showcase/* Updated props & inputs from interfaces to type aliases; minor logic tweak in job-create cleanup.
docs/* Updated documentation to remove grouped use.* API and promote thin-flat hooks from UI package.
package.json Added stricter lint/test scripts and dev dependencies (lint plugins, code mods).
eslint.config.js Added import/unicorn/sonarjs/early-return plugins and complexity/depth rules (disabled for tests).
.release-please-manifest.json Bumped package versions to 0.3.0.
Files not reviewed (1)
  • pnpm-lock.yaml: Language not supported

- Fix error message handling: getItemError returns string, not Error object
- Update WordPressStoreSelector type to match actual store behavior
- Preserve original namespace in fallback for debugging/introspection
- Add regression test for WordPress quirk: status='success' with hasFinishedResolution=false
- Fix test mocks to return undefined instead of null for error values

Addresses review comments from PR #73
@pipewrk pipewrk requested a review from Copilot October 7, 2025 18:20
Copy link
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

Copilot reviewed 53 out of 107 changed files in this pull request and generated 5 comments.

Files not reviewed (1)
  • pnpm-lock.yaml: Language not supported

pipewrk and others added 3 commits October 8, 2025 02:24
Co-authored-by: Copilot <[email protected]>
Signed-off-by: Jason Joseph Nathan <[email protected]>
Co-authored-by: Copilot <[email protected]>
Signed-off-by: Jason Joseph Nathan <[email protected]>
- Fix resetState() to match original INVALIDATE_ALL behavior
  * Remove ...initialState spread that incorrectly preserved custom fields
  * Add comment clarifying intentional clearing of all state
  * Addresses review comment about behavior change

- Document null check pattern in fetch helper functions
  * Add JSDoc explaining why each helper checks hooks independently
  * Addresses nitpick review comment about repetitive null checks
  * Current pattern maintains isolation and testability

- Auto-format code per linter rules
@pipewrk
Copy link
Contributor Author

pipewrk commented Oct 7, 2025

Re: Helper function null checks (nitpick)

The design choice is now documented! See the JSDoc comment on emitRequestEvent (lines 196-203 in commit 4393717):

/**
 * Emit request event via hooks.
 * Each helper performs its own null check for isolation and testability,
 * rather than relying on an early guard in the caller.
 */

Each helper (emitRequestEvent, emitResponseEvent, emitErrorEvent) performs its own null check intentionally. This keeps them self-contained and independently testable without coupling to the caller's state management. The pattern is consistent across all three event emission helpers.

Since this is architecture by design (not oversight), I've kept the current implementation with documentation rather than consolidating guards. 👍

@pipewrk pipewrk merged commit 6015435 into main Oct 7, 2025
6 checks passed
@pipewrk pipewrk deleted the fix/release-0.3.0 branch October 7, 2025 18:40
pipewrk added a commit that referenced this pull request Nov 8, 2025
- Fix error message handling: getItemError returns string, not Error object
- Update WordPressStoreSelector type to match actual store behavior
- Preserve original namespace in fallback for debugging/introspection
- Add regression test for WordPress quirk: status='success' with hasFinishedResolution=false
- Fix test mocks to return undefined instead of null for error values

Addresses review comments from PR #73
pipewrk added a commit that referenced this pull request Nov 8, 2025
release: 0.3.0 — React Hooks Migration & Resource API Refinements
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants