shadcn-ui / ui

Beautifully designed components that you can copy and paste into your apps. Accessible. Customizable. Open Source.
https://ui.shadcn.com
MIT License
68.52k stars 4.06k forks source link

Default value not showing the correct selected value #1361

Closed JungRama closed 2 weeks ago

JungRama commented 1 year ago

I have a button with action to set a sorting on select input. On that button i change the value on useState from latest -> price-low-high.

When the button clicked the value inside render-value class changed. but the default value for the select not changed.

const [sort, setSort] = useState<string>('latest')

<div className="flex items-center w-full md:w-auto">
  <div className="render-value">{sort}</div>
  <button onClick={()=> setSort('price-low-high')}>CHANGE SORT VALUE<button>

  <Label htmlFor="sorting" className="mr-2 text-gray-500 hidden md:block">Sorting {sort}</Label>
  <Select onValueChange={value=> selectSort(value)}
    defaultValue={sort}>
    <SelectTrigger className="w-full md:w-[200px]">
      <SelectValue placeholder="Select Sorting" />
    </SelectTrigger>
    <SelectContent id="sorting">
      <SelectItem value="latest">Latest Product {sort}</SelectItem>
      <SelectItem value={'price-low-high'}>Price: Low - High</SelectItem>
      <SelectItem value={'price-high-low'}>Price: High - Low</SelectItem>
    </SelectContent>
  </Select>
</div>
yousihy commented 1 year ago

I am having a similar issue too. It seems that "dynamically" generated SelectItem is causing an issue. In my case, I am using Zod validation library. I am supposed to select from available types of properties. The selection works and Zod is getting the value. But the item is not being displayed in the select box. It is just showing empty

<FormField
control={form.control}
name="type"
render={({ field }) => (
<FormItem className="grid grid-cols-4 items-center gap-4">
   <FormLabel className="sm:block sm:text-right">
      Type
   </FormLabel>
   <Select
      disabled={isSubmitting}
      onValueChange={field.onChange}
      defaultValue={field.value}
      >
      <FormControl>
         <SelectTrigger className="col-span-4 sm:col-span-3">
            <SelectValue placeholder="Select a property type"/>
         </SelectTrigger>
      </FormControl>
      <SelectContent className="SelectContent">
         {propTypes.map((type) => (
         <SelectItem key={type.id} value={type.id}>
            {type.name}
         </SelectItem>
         ))}
      </SelectContent>
   </Select>
</FormItem>
)}
/>

image

I am not seeing the value selected:

image

However, Zod is getting the value successfully:

image

Now, if I replace the dynamically generated values with static values as below, it will work, and I will be able to see what I selected:

<SelectContent>
   <SelectItem value="m@example.com">m@example.com</SelectItem>
   <SelectItem value="m@google.com">m@google.com</SelectItem>
   <SelectItem value="m@support.com">m@support.com</SelectItem>
</SelectContent>

Something is wrong when we generate the SelectItem dynamically

yousihy commented 1 year ago

Here is codesandbox view for your reference

codesandbox view

codingwithashu commented 11 months ago

@yousihy , have you resolved this?

hardikchopra242 commented 11 months ago

@yousihy @codingwithashu I hope you are aware of the fact that defaultValue should be used only when you do not need to control the state of the select. You might need to use value instead. See This

lucas-mirror commented 11 months ago

I was also having trouble getting this to work. But @hardikchopra242 nailed it for me. The example of usage in a form in the docs leads to this mistake (defaultValue instead of value).

image
yousihy commented 11 months ago

@yousihy , have you resolved this?

For my case, the issue was that I needed to strictly specify that the value is a string although the type was a string. This applies to ALL shadcn controls by the way.

So, I had to convert the string to a string

value={data.id.toString()}

So, the SelectContent would look like this:

<SelectContent>
     {propType.map((data)=>(
      <SelectItem key={data.id} value={data.id.toString()}>{data.name}</SelectItem>
    ))}
</SelectContent>
yousihy commented 11 months ago

@yousihy @codingwithashu I hope you are aware of the fact that defaultValue should be used only when you do not need to control the state of the select. You might need to use value instead. See This

This did not work for me or it didn't have any effect on my problem. My controls are working fine with value only. My issue was that I needed to ensure that I am passing a string to the value property of the SelectItem even though the type of that value is actually a string. See my comment above

Yolosopher2 commented 11 months ago

@yousihy Thanks!

data.id.toString()

this saved me to waste much more time on this

codingwithashu commented 11 months ago

Not worked image

Yolosopher2 commented 11 months ago

@codingwithashu

Not worked image

First of all, if you are using value, there is no reason to also use defaultValue.

Inside