Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix(select): enable defaultValue to work correctly by removing rehydration hack #3545

Merged
merged 10 commits into from
Oct 17, 2023
11 changes: 11 additions & 0 deletions .changeset/thirty-forks-poke.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
---
"@twilio-paste/select": patch
"@twilio-paste/core": patch
---

[Select] fix the hydration issue which caused the `defaultValue` prop to not be respected.

Since the React v18 upgrade, we were only rendering the children options after the component and html select
wrapper had mounted. The select would mount with a `defaultValue` of a child that didn't exist, then the
children would be added, so it wouldn't know what value to select. By adding a `key` prop to the select,
it now knows to re-render on mount with the children, and can properly lookup the correct value now.
2 changes: 2 additions & 0 deletions packages/paste-core/components/select/src/Select.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -87,6 +87,7 @@ const Select = React.forwardRef<HTMLSelectElement, SelectProps>(
setShowOptions(true);
}, []);

// N.B. `key` on SelectElement fixes an issue where defaultValue is not respected
return (
<InputBox
disabled={disabled}
Expand All @@ -107,6 +108,7 @@ const Select = React.forwardRef<HTMLSelectElement, SelectProps>(
multiple={multiple}
size={multiple ? size : 0}
variant={variant}
key={showOptions ? "show" : "hide"}
>
{showOptions && children}
</SelectElement>
Expand Down
17 changes: 16 additions & 1 deletion packages/paste-core/components/select/stories/select.stories.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -45,9 +45,24 @@ export const DefaultSelect = (): React.ReactNode => {
</>
);
};

DefaultSelect.storyName = "Select";

export const DefaultValueSelect = (): React.ReactNode => {
const uid = useUID();
return (
<>
<Label htmlFor={uid}>Label</Label>
<Select id={uid} defaultValue="option-2" onFocus={action("handleFocus")} onBlur={action("handleBlur")}>
<Option value="option-1">Option 1</Option>
<Option value="option-2">Option 2</Option>
<Option value="option-3">Option 3</Option>
<Option value="option-4">Option 4</Option>
</Select>
<HelpText>Info that helps a user with this field.</HelpText>
</>
);
};

export const SelectRequired = (): React.ReactNode => {
const uid = useUID();
const [value, setValue] = React.useState("Select - Required");
Expand Down
Loading