Skip to content

Commit 6a31a1d

Browse files
committed
refactor: remove select dual states
1 parent 5a6d7d2 commit 6a31a1d

File tree

8 files changed

+37
-38
lines changed

8 files changed

+37
-38
lines changed

apps/site/components/Downloads/Release/InstallationMethodDropdown.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -76,7 +76,7 @@ const InstallationMethodDropdown: FC = () => {
7676
return (
7777
<Select<InstallationMethod | ''>
7878
values={grouppedMethods}
79-
defaultValue={release.installMethod}
79+
value={release.installMethod}
8080
loading={release.os === 'LOADING' || release.installMethod === ''}
8181
ariaLabel={t('layouts.download.dropdown.platform')}
8282
onChange={platform => platform && release.setInstallMethod(platform)}

apps/site/components/Downloads/Release/OperatingSystemDropdown.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -52,7 +52,7 @@ const OperatingSystemDropdown: FC<OperatingSystemDropdownProps> = () => {
5252
return (
5353
<Select<OperatingSystem>
5454
values={parsedOperatingSystems}
55-
defaultValue={release.os !== 'LOADING' ? release.os : undefined}
55+
value={release.os !== 'LOADING' ? release.os : undefined}
5656
loading={release.os === 'LOADING'}
5757
placeholder={t('layouts.download.dropdown.unknown')}
5858
ariaLabel={t('layouts.download.dropdown.os')}

apps/site/components/Downloads/Release/PackageManagerDropdown.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,7 @@ const PackageManagerDropdown: FC = () => {
3737
return (
3838
<Select<PackageManager>
3939
values={parsedPackageManagers}
40-
defaultValue={release.packageManager}
40+
value={release.packageManager}
4141
loading={release.os === 'LOADING' || release.installMethod === ''}
4242
ariaLabel={t('layouts.download.dropdown.packageManager')}
4343
onChange={manager => release.setPackageManager(manager)}

apps/site/components/Downloads/Release/PlatformDropdown.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -60,7 +60,7 @@ const PlatformDropdown: FC = () => {
6060
return (
6161
<Select<Platform>
6262
values={parsedPlatforms}
63-
defaultValue={release.platform !== '' ? release.platform : undefined}
63+
value={release.platform !== '' ? release.platform : undefined}
6464
loading={release.os === 'LOADING' || release.platform === ''}
6565
placeholder={t('layouts.download.dropdown.unknown')}
6666
ariaLabel={t('layouts.download.dropdown.platform')}

packages/ui-components/src/Common/Select/NoScriptSelect/index.tsx

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,17 +7,18 @@ import type { StatelessSelectProps } from '#ui/Common/Select/StatelessSelect';
77

88
const WithNoScriptSelect = <T extends string>({
99
as,
10+
defaultValue,
1011
...props
1112
}: StatelessSelectProps<T>) => {
1213
const id = useId();
1314
const selectId = `select-${id.replace(/[^a-zA-Z0-9]/g, '')}`;
1415

1516
return (
1617
<>
17-
<Select {...props} fallbackClass={selectId} />
18+
<Select {...props} value={defaultValue} fallbackClass={selectId} />
1819
<noscript>
1920
<style>{`.${selectId} { display: none!important; }`}</style>
20-
<StatelessSelect {...props} as={as} />
21+
<StatelessSelect {...props} defaultValue={defaultValue} as={as} />
2122
</noscript>
2223
</>
2324
);

packages/ui-components/src/Common/Select/StatelessSelect/index.tsx

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -15,8 +15,10 @@ type StatelessSelectConfig = {
1515
as?: LinkLike | 'div';
1616
};
1717

18-
export type StatelessSelectProps<T extends string> = SelectProps<T> &
19-
StatelessSelectConfig;
18+
export type StatelessSelectProps<T extends string> = Omit<SelectProps<T>, 'value'> &
19+
StatelessSelectConfig & {
20+
defaultValue?: T;
21+
};
2022

2123
const StatelessSelect = <T extends string>({
2224
values = [],

packages/ui-components/src/Common/Select/index.stories.tsx

Lines changed: 23 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
import { useArgs } from 'storybook/preview-api';
2+
13
import Select from '#ui/Common/Select';
24
import StatelessSelect from '#ui/Common/Select/StatelessSelect';
35
import * as OSIcons from '#ui/Icons/OperatingSystem';
@@ -10,22 +12,22 @@ type Meta = MetaObj<typeof Select>;
1012
export const Default: Story = {
1113
args: {
1214
values: ['v20.8.0', 'v19.9.0', 'v18.18.0', 'v17.9.1', 'v16.20.2'],
13-
defaultValue: 'v16.20.2',
15+
value: 'v16.20.2',
1416
label: 'Node.js version',
1517
},
1618
};
1719

1820
export const WithoutLabel: Story = {
1921
args: {
2022
values: ['v20.8.0', 'v19.9.0', 'v18.18.0', 'v17.9.1', 'v16.20.2'],
21-
defaultValue: 'v16.20.2',
23+
value: 'v16.20.2',
2224
},
2325
};
2426

2527
export const WithScrollButtons: Story = {
2628
args: {
2729
values: Array.from({ length: 100 }, (_, i) => `Item ${i}`),
28-
defaultValue: 'Item 50',
30+
value: 'Item 50',
2931
},
3032
};
3133

@@ -35,14 +37,8 @@ export const DropdownLabel: Story = {
3537
{
3638
label: 'Getting Started',
3739
items: [
38-
{
39-
value: 'section-1',
40-
label: 'Getting Started',
41-
},
42-
{
43-
value: 'section-2',
44-
label: 'How to install Node.js',
45-
},
40+
{ value: 'section-1', label: 'Getting Started' },
41+
{ value: 'section-2', label: 'How to install Node.js' },
4642
{
4743
value: 'section-3',
4844
label: 'How much JavaScript do you need to know to use Node.js?',
@@ -51,18 +47,12 @@ export const DropdownLabel: Story = {
5147
value: 'section-4',
5248
label: 'Differences between Node.js and the Browser',
5349
},
54-
{
55-
value: 'section-5',
56-
label: 'The V8 JavaScript Engine',
57-
},
50+
{ value: 'section-5', label: 'The V8 JavaScript Engine' },
5851
{
5952
value: 'section-6',
6053
label: 'An introduction to the npm package manager',
6154
},
62-
{
63-
value: 'section-7',
64-
label: 'ECMAScript 2015 (ES6) and beyond',
65-
},
55+
{ value: 'section-7', label: 'ECMAScript 2015 (ES6) and beyond' },
6656
{
6757
value: 'section-8',
6858
label: 'Node.js, the difference between development and production',
@@ -104,7 +94,7 @@ export const InlineSelect: Story = {
10494
],
10595
},
10696
],
107-
defaultValue: 'macos',
97+
value: 'macos',
10898
inline: true,
10999
},
110100
};
@@ -118,4 +108,16 @@ export const WithNoScriptSelect: Story = {
118108
),
119109
};
120110

121-
export default { component: Select } as Meta;
111+
export default {
112+
component: Select,
113+
render: (args) => {
114+
const [, setArgs] = useArgs();
115+
116+
const onChange = (value: string) => {
117+
args.onChange?.(value);
118+
setArgs({ value });
119+
};
120+
121+
return <Select {...args} onChange={onChange} />;
122+
},
123+
} as Meta;

packages/ui-components/src/Common/Select/index.tsx

Lines changed: 3 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
import { ChevronDownIcon, ChevronUpIcon } from '@heroicons/react/24/outline';
44
import * as SelectPrimitive from '@radix-ui/react-select';
55
import classNames from 'classnames';
6-
import { useEffect, useId, useMemo, useState } from 'react';
6+
import { useId, useMemo } from 'react';
77

88
import Badge, { type BadgeKind } from '#ui/Common/Badge';
99
import Skeleton from '#ui/Common/Skeleton';
@@ -33,7 +33,7 @@ export type SelectGroup<T extends string> = {
3333

3434
export type SelectProps<T extends string> = {
3535
values: Array<SelectGroup<T>> | Array<T> | Array<SelectValue<T>>;
36-
defaultValue?: T;
36+
value?: T;
3737
placeholder?: string;
3838
label?: string;
3939
inline?: boolean;
@@ -54,7 +54,7 @@ export type SelectProps<T extends string> = {
5454

5555
const Select = <T extends string>({
5656
values = [],
57-
defaultValue,
57+
value,
5858
placeholder,
5959
label,
6060
inline,
@@ -67,9 +67,6 @@ const Select = <T extends string>({
6767
fallbackClass = '',
6868
}: SelectProps<T>): ReactNode => {
6969
const id = useId();
70-
const [value, setValue] = useState(defaultValue);
71-
72-
useEffect(() => setValue(defaultValue), [defaultValue]);
7370

7471
const mappedValues = useMemo(() => mapValues(values), [values]) as Array<
7572
SelectGroup<T>
@@ -121,10 +118,7 @@ const Select = <T extends string>({
121118
// eslint-disable-next-line @eslint-react/exhaustive-deps
122119
}, [JSON.stringify(values)]);
123120

124-
// Both change the internal state and emit the change event
125121
const handleChange = (value: T) => {
126-
setValue(value);
127-
128122
if (typeof onChange === 'function') {
129123
onChange(value);
130124
}

0 commit comments

Comments
 (0)