1

I am creating a dropdown component but typescript throws several errors on the options.map and selectedOption.title cases:

import React, { useRef,useState, useEffect } from "react";
import useToggle from '../hooks/useToggle';
import  useDetectOutsideClick  from '../hooks/useOutsideClick';

import "./select.scss";
interface TProduct {
    title?: string;
    options?: [];
    getDropDownValue?: any;
  }

  interface TOption {
    title?: string;
    value?: string;
    id?: any;
  }

const Select = (props: TProduct) => {
    let { title, options, getDropDownValue } = props;
    const dropdownRef = useRef(null);
    const [visibility, setVisibility] =  useDetectOutsideClick(dropdownRef, false);
      const [selectedOption, setSelectedOption] = useState<TOption>({});
  
      return (
          
              <div
          className="base-select"
          ref={dropdownRef}
                  onClick={e =>  {
                      setVisibility(!visibility);
                  
                  }}
              >
                  <div className="selected-option">
                      <span
                          title={
                              selectedOption === ""
                                  ? title
                                  : selectedOption.title
                          }
                      >
                          {selectedOption === ""
                              ? title
                              : selectedOption.title.length <= 20
                              ? selectedOption.title
                              : selectedOption && selectedOption.title  && `${selectedOption.title.slice(0, 20)}`}
                      </span>
                      
                  </div>
                  {visibility && (
                      <div className="options">
                          <ul>
                      
                              {options
                                  .map((option) => (
                                      <li
                                          key={index}
                                          className={
                                             selectedOption && selectedOption ===       option
                                                  ? "active-option"
                                                  : ''
                                          }
                                          onClick={() => {
                        setSelectedOption(option);
                        getDropDownValue(option);
                       
                      }
                                          }
                                      >
                                          {option.title}
                                      </li>
                                  ))}
                          </ul>
                      </div>
                  )}
              </div>
      );
     };

    export default Select

So both looping of the list items and the titles are throwing error for options type and selectedOptions.title type Object is possibly undefined

What is wrong and how can be it fixed?

3
  • add a ? to check for the availability of the object before accessing the property. such as possiblyUndefinedObject?.title Commented Sep 25, 2021 at 20:02
  • I also suggest updating the && operator to selectedOption?.id === option.id, u can't possibly match an object such as selectedOption to another using the == or ===. Commented Sep 25, 2021 at 20:05
  • @SultanH. it shows the error in key= {index} as well as in option.title in the loop. I guess ? marks are not solving the problem. If it's possible can you please answer the question? Commented Sep 25, 2021 at 20:15

1 Answer 1

1

It's fixable by safe typing your option and selectedOption with the ? operator from TS, and adding index to your options.map callback function.

<div
    className="base-select"
    ref={dropdownRef}
    onClick={e =>  {
      setVisibility(!visibility);
    }}
  >
    <div className="selected-option">
      <span
        title={
          selectedOption === ""
            ? title
            : selectedOption?.title
        }
      >
        {selectedOption === ""
          ? title
          : selectedOption?.title?.length <= 20
            ? selectedOption?.title
            : selectedOption?.title && `${selectedOption?.title?.slice(0, 20)}`}
      </span>

    </div>
    {visibility && (
      <div className="options">
        <ul>
          {options
            .map((option, index) => (
              <li
                key={index}
                className={
                  selectedOption?.id === option?.id
                    ? "active-option"
                    : ""
                }
                onClick={() => {
                  setSelectedOption(option);
                  getDropDownValue(option);
                }}
              >
                {option?.title}
              </li>
            ))}
        </ul>
      </div>
    )}
  </div>

I strongly suggest strictly typing the props of any react component that you are creating, TS is most usable here.

for instance:

type CustomSelectProps = {
  options?: Array<TOption>;
  title?: string;
  getDropDownValue?: (option: TOption) => void;
}
const Select: React.FC<CustomSelectProps> = (props) => {
  // ...component content...
}

Sign up to request clarification or add additional context in comments.

2 Comments

It still shows error for <span title={ selectedOption === "" ? title : selectedOption?.title } > {selectedOption === "" ? title : selectedOption?.title.length <= 20 ? selectedOption?.title : selectedOption?.title && ${selectedOption?.title.slice(0, 20)}} </span>
Updated, @NewTechLover just apply the same concept there.. since selectedOption is possibly undefined, in that case the title itself would be, thus, we would be doing sth like undefined.slice which isn't possible there.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.