0

I have a problem with set State in dropdown semantic-ui-react. I am using typescript in my code. The selected category value doesn't change and always returns an empty string "". How can I fix this?

import debounce from "lodash.debounce";
import { observer } from "mobx-react-lite";
import React, { SyntheticEvent, useContext, useState } from "react";
import {
  Dropdown,
  DropdownItemProps,
  DropdownProps,
  Form,
  InputOnChangeData,
  Popup,
} from "semantic-ui-react";
import { RootStoreContext } from "../../../app/stores/rootStore";

const regex = new RegExp("^[a-zA-Z0-9 ]+$");

interface IProps {
  loading: boolean;
}

const PurchaseDetailsFilter: React.FC<IProps> = ({ loading }) => {
  const rootStore = useContext(RootStoreContext);
  const {
    setFilter,
    itemCount,
    loadPurchaseDetails,
    categoryId,
    setCategoryId,
  } = rootStore.purchaseDetailStore;

  const { purchaseCategories } = rootStore.purchaseCategoryStore;

  const purchaseCategoriesList: any = purchaseCategories.map((data) => {
    return { key: data.id, text: data.name, value: data.id };
  });

  const categoryOptions: DropdownItemProps[] = [
    { key: "all", value: "all", text: "All" },
  ].concat(purchaseCategoriesList);

  const [selectedCategory, setSelectedCategory] = useState("");

  const [filterValid, setFilterValid] = useState(true);
  
  const f = debounce((value: string) => {
    if (value !== "" && !regex.test(value)) {
      setFilterValid(false);
      setFilter(value);
    } else {
      setFilterValid(true);
      console.log(loading);
      setFilter(value);     
      loadPurchaseDetails();
    }
  }, 500);

  const cat = debounce((value: string) => {    
    console.log(value);    
    setSelectedCategory(value as string);
    console.log(selectedCategory);
    setCategoryId((value ==="all" ? "" : value) as string);
    loadPurchaseDetails();        
  }, 500);

  const handleOnChange = (
    event: React.ChangeEvent<HTMLInputElement>,
    { value }: InputOnChangeData
  ) => {
    f(value);
  };

  let popupMessage = "";
  if (!filterValid) {
    popupMessage = "Invalid character.";
  } else if (itemCount === 0) {
    popupMessage = "No results found.";
  }
  
  const handleSelectedCategory = (
    event: SyntheticEvent<HTMLElement>,
    {value}: DropdownProps
  ) => {      
    console.log(value);    
    setSelectedCategory(String(value));
    console.log(selectedCategory);
    setCategoryId((value ==="all" ? "" : value) as string);
    loadPurchaseDetails();    
  };

  return (
    <Form>
      <Form.Group>
        <Form.Field>
          <Popup
            trigger={
              <Form.Input
                placeholder={"Enter a filter."}
                name={"filter"}
                error={!filterValid}
                label={"Filter"}
                onChange={handleOnChange}               
                icon={"search"}
                loading={loading}
              />
            }
            content={popupMessage}
            on={"click"}
            open={!filterValid || itemCount === 0}
            position={"right center"}
          />
        </Form.Field>
        <Form.Field style={{ marginLeft: "10em" }}>
          <label>Category</label>
          <Dropdown    
            //defaultValue="All"
            //value={categoryId}     
            value={selectedCategory}
            onChange={handleSelectedCategory}      
            //defaultValue={categoryOptions[0].value}              
            placeholder="Choose an category"
            options={categoryOptions}
            selection
          />
        </Form.Field>
        <Form.Field>
          <label>Project</label>
          <Dropdown placeholder="Choose an option" />
        </Form.Field>
        <Form.Field>
          <label>Supplier</label>
          <Dropdown placeholder="Choose an option" />
        </Form.Field>
      </Form.Group>
    </Form>
  );
};

export default observer(PurchaseDetailsFilter);
Bakri
  • 11
  • 2
  • Maybe I'm missing something, what am I looking at here? Is this a functional component? It looks like TSX but it appears to be missing a return statement. – Nick Winner Nov 15 '20 at 11:50
  • 1
    I don't see you passing a value to the onChange handler. Try something like this: onChange={(event)=>handleSelectedCategory(event, value)} – MWO Nov 15 '20 at 12:33
  • yes it is a functional component. I'm soory not include all the code. Below is full code for the functional component. – Bakri Nov 15 '20 at 13:33

2 Answers2

1

maybe what you are looking for is this one:

      const handleSelectedCategory = (
        event: SyntheticEvent<HTMLElement>,
        {value}: DropdownProps
      ) => {      
        console.log(value);    
        setSelectedCategory(String(value));
        console.log(selectedCategory);
        setCategoryId(String(value ==="all" ? "" : value));
        loadPurchaseDetails();      
      };

notice that I changed value as string to be String(value). I once fiddle around with TypeScript, but I forget how as string casting works. You might find better explanation here: https://stackoverflow.com/a/32607656/7467018

ybbond
  • 51
  • 1
  • 4
  • I have tried with String(value), and still same, doesn't update the value. – Bakri Nov 15 '20 at 13:31
  • sorry I've been busy. I just read into your edited question, did you previously happen to use the debounced `cat` function somewhere? I look into [semantic-ui-react§usage-allow-additions](https://react.semantic-ui.com/modules/dropdown/#usage-allow-additions) docs and your implementation looks correct – ybbond Dec 10 '20 at 23:05
0

Have a look at the below code comment

const handleSelectedCategory = (
    event: SyntheticEvent<HTMLElement>,
    { value }: DropdownProps
) => {
    console.log(value); // If this value is string i.e "Hello World", then just call setSelectedCategory(value);
    setSelectedCategory(value as string); // Not required. Just call setSelectedCategory(value) if value is string.
    console.log(selectedCategory); 
    setCategoryId((value === "all" ? "" : value) as string); // Curious, where is setCategoryId froming from?
    loadPurchaseDetails();
};
Grey
  • 489
  • 3
  • 7