Search code examples
reactjstypescriptselectshadcnuiradix-ui

Reset SELECT value for ShadCN/UI <Select> component


I have a page with multiple <Select> dropdowns and they are dependent on each other. My problem is that when I change a superceding select, the ones depending on it do not reset. sample code:

<Select
 onvaluechange ={value=>setvalues(values=>{...values, make: value, sku:undefined, model:undefined})}
 value=values.make
>
  <SelectTrigger>
    <SelectValue placeholder="manufacturer" />
  </SelectTrigger>
  <SelectContent>
    {loop to fill <SelectItem>item</SelectItem> dynamically based on a DB list}
  </SelectContent>
</Select>
<Select
 onvaluechange ={value=>setvalues(values=>{...values, model: value, sku:undefined})}
 value=values.model
>
  <SelectTrigger>
    <SelectValue placeholder="model" />
  </SelectTrigger>
  <SelectContent>
    {loop to fill <SelectItem> dynamically based on a DB list}
  </SelectContent>
</Select>
<Select
 onvaluechange ={value=>setvalues(values=>{...values, sku: value})}
 value=values.sku
>
  <SelectTrigger>
    <SelectValue placeholder="sku" />
  </SelectTrigger>
  <SelectContent>
    {loop to fill <SelectItem> dynamically based on a DB list}
  </SelectContent>
</Select>

The problem is that the selection of Manufacturer or model does not propagate the resets. Neither does me creating an additional State object for each dependant list and calling setState, ie, setSku(undefined). The Select doesn't seem to have an id attribute so I cant manually reset it by manually finding it from the document neither. I have been banging my head about this since Monday and will really appreciate any help rendered.

Update: So i used <SelectValue>{state}</SelectValue> inside the SelectTrigger to get the display value to change. My new problem however is that despite this the value remains selected so if I were to switch to a Manufacturer with a similarly names model I am unable to contiue as the model is 'autoselected' (problem here is that I use a hidden to capture the values and the inputs do actually respect the state changes). I would like the whole select to clear.

I have read this question, this question, and this question and none of them seem to get the job done for me.


Solution

  • I managed to resolve it by not using the values object and instead creating individual state objects for each Select.

    Afterwards I set each state to string or undefined and in the value props of each Select, I set the value to either the state value or an empty string ''. Finally to ensure that the 'dependency' Select updates its 'children', I set the states to undefined in the dependency onValueChanged().

    Final code:

    <Select
     onvalueChange ={
        setMake(value)
        setSku(undefined)
    }
     value={make ||''}
    >
      <SelectTrigger>
        <SelectValue placeholder="manufacturer" >
          {make || "manufacturer"}
        </SelectValue >
      </SelectTrigger>
      <SelectContent>
        {loop to fill <SelectItem>item</SelectItem> dynamically based on a DB list}
      </SelectContent>
    </Select>
    <Select
     onvalueChange ={
        setSku(value)
    }
     value={sku ||''}
    >
      <SelectTrigger>
        <SelectValue placeholder="model" >
          {sku || "model"}
        </SelectValue >
      </SelectTrigger>
      <SelectContent>
        {loop to fill <SelectItem>item</SelectItem> dynamically based on a DB list}
      </SelectContent>
    </Select>
    

    If tis does not work for you try setting the 'child' values to undefined in a useEffect. i.e.

    useEffect(()=>{
       setSku(undefined)
    },[make]);