Skip to content

feat(useList): accept readonly array inputs - #575

Open
GamjaIsMine02 wants to merge 3 commits into
toss:mainfrom
GamjaIsMine02:feat/use-list-readonly-inputs
Open

GamjaIsMine02 wants to merge 3 commits into
toss:mainfrom
GamjaIsMine02:feat/use-list-readonly-inputs

Conversation

@GamjaIsMine02

@GamjaIsMine02 GamjaIsMine02 commented Oct 21, 2026 •

Copy link
Copy Markdown
Contributor

Overview

useList returns a readonly array, but its initial state and setAll currently require mutable arrays. Callers must copy readonly arrays just to satisfy these parameter types.

This PR accepts readonly T[] for both inputs. A list returned by useList can be passed directly as another useList's initial state or to setAll, without a caller-side array copy. Mutable arrays remain valid inputs.

Internal state is also typed as readonly T[], allowing TypeScript to catch accidental in-place array mutations during future implementation changes.

Tests cover readonly tuple inference, updates and reset with a frozen initial array, and passing frozen arrays and returned lists to setAll.

The JSDoc, generated English documentation, all four translations, and generated plugin reference are updated. A patch changeset is included.

Checklist

  • Did you write the test code?
  • Have you run yarn run fix to format and lint the code and docs?
  • Have you run yarn run test:coverage to make sure there is no uncovered line?
  • Did you write the JSDoc?

@changeset-bot

changeset-bot Bot commented Oct 21, 2026 •

Copy link
Copy Markdown

🦋 Changeset detected

Latest commit: 33e3d78

The changes in this PR will be included in the next version bump.

This PR includes changesets to release 1 package
Name Type
react-simplikit Patch

Not sure what this means? Click here to learn what changesets are.

Click here if you're a maintainer who wants to add another changeset to this PR

@codecov-commenter

codecov-commenter commented Oct 21, 2026 •

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 100.00%. Comparing base (cf0dd83) to head (33e3d78).

Additional details and impacted files

Impacted file tree graph

@@            Coverage Diff            @@
##              main      #575   +/-   ##
=========================================
  Coverage   100.00%   100.00%           
=========================================
  Files           69        69           
  Lines         2281      2281           
  Branches       737       737           
=========================================
  Hits          2281      2281           
🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

* const [list, actions] = useList<string>(initialItems);
*
* // Add an item
* actions.push('cherry');

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

why did you changed example here?

I think 'as const' makes it confusing

(also I think generic type in here is unnecessary)

const [list, actions] = useList(['apple', 'banana']);

I suggest this example

what do you think about this? I wanna know why did you changed here

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

I changed the example to demonstrate the newly supported readonly input. With as const, the element type is narrowed to 'apple' | 'banana', so I kept <string> to allow the later calls such as push('orange').

But I agree that this unnecessarily complicates an example meant to show the hook’s basic usage! I’ll restore the original example and cover readonly inputs in the tests. Thanks for pointing this out!

Comment on lines -10 to 15
const result = renderHookSSR.serverOnly(() => useList(['a', 'b']));
const initialState = ['a', 'b'] as const;
const result = renderHookSSR.serverOnly(() => useList(initialState));

expect(result.current[0]).toEqual(['a', 'b']);
expectTypeOf(result.current[0]).toEqualTypeOf<ReadonlyArray<'a' | 'b'>>();
});

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

why did you change this test?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

I intended to add coverage for readonly tuple inputs, but changing the existing test was a mistake. I’ve restored the original SSR test and moved the readonly tuple inference check into a separate test case!

@GamjaIsMine02 GamjaIsMine02 left a comment

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Thanks for the review!

I simplified the usage examples as suggested and restored the original SSR test. The readonly tuple inference check is now covered in a separate test case.

* const [list, actions] = useList<string>(initialItems);
*
* // Add an item
* actions.push('cherry');

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

I changed the example to demonstrate the newly supported readonly input. With as const, the element type is narrowed to 'apple' | 'banana', so I kept <string> to allow the later calls such as push('orange').

But I agree that this unnecessarily complicates an example meant to show the hook’s basic usage! I’ll restore the original example and cover readonly inputs in the tests. Thanks for pointing this out!

Comment on lines -10 to 15
const result = renderHookSSR.serverOnly(() => useList(['a', 'b']));
const initialState = ['a', 'b'] as const;
const result = renderHookSSR.serverOnly(() => useList(initialState));

expect(result.current[0]).toEqual(['a', 'b']);
expectTypeOf(result.current[0]).toEqualTypeOf<ReadonlyArray<'a' | 'b'>>();
});

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

I intended to add coverage for readonly tuple inputs, but changing the existing test was a mistake. I’ve restored the original SSR test and moved the readonly tuple inference check into a separate test case!

@hyesungoh hyesungoh left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Great 👍 👍

@hyesungoh

Copy link
Copy Markdown
Member

One small request for next time @GamjaIsMine02

if you change something that this PR doesn't need (like the example or the old test here)
please tell us why in the self reviewed comments

Also, please check your diff once before you ask for a review 🙏
It really helps us review faster

This branch has not been deployed

No deployments
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