fix(autocomplete): controlled state logic (#2969)

* fix(autocomplete): autocomplete controlled state (#2955)

* chore(autocomplete): add changeset

* Update packages/components/autocomplete/__tests__/autocomplete.test.tsx

---------

Co-authored-by: Junior Garcia <jrgarciadev@gmail.com>
This commit is contained in:
chirokas 2024-06-15 08:08:09 +08:00 committed by GitHub
parent 0e4213ce25
commit 255c641f96
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
3 changed files with 76 additions and 1 deletions

View File

@ -0,0 +1,5 @@
---
"@nextui-org/autocomplete": patch
---
Fix autocomplete controlled state (#2955)

View File

@ -48,6 +48,21 @@ const itemsSectionData = [
},
];
const ControlledAutocomplete = <T = object>(props: AutocompleteProps<T>) => {
const [selectedKey, setSelectedKey] = React.useState<React.Key>("cat");
return (
<Autocomplete
{...props}
aria-label="Favorite Animal"
label="Favorite Animal"
selectedKey={selectedKey}
onSelectionChange={setSelectedKey}
/>
);
};
const AutocompleteExample = (props: Partial<AutocompleteProps> = {}) => (
<Autocomplete label="Favorite Animal" {...props}>
<AutocompleteItem key="penguin" value="penguin">
@ -62,6 +77,7 @@ const AutocompleteExample = (props: Partial<AutocompleteProps> = {}) => (
</Autocomplete>
);
describe("Autocomplete", () => {
it("should render correctly", () => {
const wrapper = render(<AutocompleteExample />);
@ -559,6 +575,60 @@ describe("Autocomplete", () => {
});
});
});
it("should work when key equals textValue", async () => {
const wrapper = render(
<Autocomplete
aria-label="Favorite Animal"
data-testid="when-key-equals-textValue"
defaultSelectedKey="cat"
items={itemsData}
label="Favorite Animal"
>
{(item) => <AutocompleteItem key={item.value}>{item.value}</AutocompleteItem>}
</Autocomplete>,
);
const autocomplete = wrapper.getByTestId("when-key-equals-textValue");
const user = userEvent.setup();
await user.click(autocomplete);
expect(autocomplete).toHaveValue("cat");
expect(autocomplete).toHaveAttribute("aria-expanded", "true");
let listboxItems = wrapper.getAllByRole("option");
await user.click(listboxItems[1]);
expect(autocomplete).toHaveValue("dog");
expect(autocomplete).toHaveAttribute("aria-expanded", "false");
});
it("should work when key equals textValue (controlled)", async () => {
const wrapper = render(
<ControlledAutocomplete data-testid="when-key-equals-textValue" items={itemsData}>
{(item) => <AutocompleteItem key={item.value}>{item.value}</AutocompleteItem>}
</ControlledAutocomplete>,
);
const autocomplete = wrapper.getByTestId("when-key-equals-textValue");
const user = userEvent.setup();
await user.click(autocomplete);
expect(autocomplete).toHaveValue("cat");
expect(autocomplete).toHaveAttribute("aria-expanded", "true");
let listboxItems = wrapper.getAllByRole("option");
await user.click(listboxItems[1]);
expect(autocomplete).toHaveValue("dog");
expect(autocomplete).toHaveAttribute("aria-expanded", "false");
});
});
describe("Autocomplete with React Hook Form", () => {

View File

@ -314,7 +314,7 @@ export function useAutocomplete<T extends object>(originalProps: UseAutocomplete
const key = inputRef.current.value;
const item = state.collection.getItem(key);
if (item) {
if (item && state.inputValue !== item.textValue) {
state.setSelectedKey(key);
state.setInputValue(item.textValue);
}