Welcome to ShenZhenJia Knowledge Sharing Community for programmer and developer-Open, Learning and Share
menu search
person
Welcome To Ask or Share your Answers For Others

Categories

I am making a searchable Dropdown and getting following eslint warning:

React Hook useEffect has missing dependencies: 'filterDropDown' and 'restoreDropDown'. Either include them or remove the dependency array.

import React, { useState, useEffect, useCallback } from "react";
const SearchableDropDown2 = () => {
  const [searchText, setSearchText] = useState("");
  const [dropdownOptions, setDropdownOptions] = useState([
    "React",
    "Angular",
    "Vue",
    "jQuery",
    "Nextjs",
  ]);
  const [copyOfdropdownOptions, setCopyOfDropdownOptions] = useState([
    ...dropdownOptions,
  ]);
  const [isExpand, setIsExpand] = useState(false);

  useEffect(() => {
    searchText.length > 0 ? filterDropDown() : restoreDropDown();
  }, [searchText]);

  const onClickHandler = (e) => {
    setSearchText(e.target.dataset.myoptions);
    setIsExpand(false);
  };

  const onSearchDropDown = () => setIsExpand(true);

  const closeDropDownHandler = () => setIsExpand(false);

  const filterDropDown = useCallback(() => {
    const filteredDropdown = dropdownOptions.filter((_) =>
      _.toLowerCase().includes(searchText.toLowerCase())
    );
    setDropdownOptions([...filteredDropdown]);
  }, [dropdownOptions]);

  const restoreDropDown = () => {
    if (dropdownOptions.length !== copyOfdropdownOptions.length) {
      setDropdownOptions([...copyOfdropdownOptions]);
    }
  };

  const onSearchHandler = (e) => setSearchText(e.target.value.trim());
  return (
    <div style={styles.mainContainer}>
      <input
        type="search"
        value={searchText}
        onClick={onSearchDropDown}
        onChange={onSearchHandler}
        style={styles.search}
        placeholder="search"
      />
      <button disabled={!isExpand} onClick={closeDropDownHandler}>
        -
      </button>
      <div
        style={
          isExpand
            ? styles.dropdownContainer
            : {
                ...styles.dropdownContainer,
                height: "0vh",
              }
        }
      >
        {dropdownOptions.map((_, idx) => (
          <span
            onClick={onClickHandler}
            style={styles.dropdownOptions}
            data-myoptions={_}
            value={_}
          >
            {_}
          </span>
        ))}
      </div>
    </div>
  );
};

const styles = {
  mainContainer: {
    padding: "1vh 1vw",
    width: "28vw",
    margin: "auto auto",
  },
  dropdownContainer: {
    width: "25vw",
    background: "grey",
    height: "10vh",
    overflow: "scroll",
  },
  dropdownOptions: {
    display: "block",
    height: "2vh",
    color: "white",
    padding: "0.2vh 0.5vw",
    cursor: "pointer",
  },
  search: {
    width: "25vw",
  },
};

I tried wrapping the filterDropDown in useCallback but then the searchable dropdown stopped working.

Following are the changes incorporating useCallback:

const filterDropDown = useCallback(() => {
  const filteredDropdown = dropdownOptions.filter((_) =>
    _.toLowerCase().includes(searchText.toLowerCase())
  );
  setDropdownOptions([...filteredDropdown]);
}, [dropdownOptions, searchText]);

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
thumb_up_alt 0 like thumb_down_alt 0 dislike
199 views
Welcome To Ask or Share your Answers For Others

1 Answer

My suggestion would be to not use useEffect at all in the context of what you are achieving.

import React, {useState} from 'react';

const SearchableDropDown = () => {
    const [searchText, setSearchText] = useState('');
    const dropdownOptions = ['React','Angular','Vue','jQuery','Nextjs'];
    const [isExpand, setIsExpand] = useState(false);


    const onClickHandler = e =>  {
        setSearchText(e.target.dataset.myoptions);
        setIsExpand(false);
    }

    const onSearchDropDown = () => setIsExpand(true);
    const closeDropDownHandler = () => setIsExpand(false);
    const onSearchHandler = e => setSearchText(e.target.value.trim());

    return (
        <div style={styles.mainContainer}>
            <input
                type="search"
                value={searchText}
                onClick={onSearchDropDown}
                onChange={onSearchHandler}
                style={styles.search}
                placeholder="search"
            />
            <button disabled={!isExpand} onClick={closeDropDownHandler}>
                -
            </button>
            <div
                style={
                    isExpand
                        ? styles.dropdownContainer
                        : {
                                ...styles.dropdownContainer,
                                height: '0vh',
                            }
                }
            >
                {dropdownOptions
                    .filter(opt => opt.toLowerCase().includes(searchText.toLowerCase()))
                    .map((option, idx) =>
                        <span key={idx} onClick={onClickHandler} style={styles.dropdownOptions} data-myoptions={option} value={option}>
                            {option}
                        </span>
                    )}
            </div>
        </div>
    );
};

const styles = {
    mainContainer: {
        padding: '1vh 1vw',
        width: '28vw',
        margin: 'auto auto'
    },
    dropdownContainer: {
        width: '25vw',
        background: 'grey',
        height: '10vh',
        overflow: 'scroll'
    },
    dropdownOptions: {
        display: 'block',
        height: '2vh',
        color: 'white',
        padding: '0.2vh 0.5vw',
        cursor: 'pointer',
    },
    search: {
        width: '25vw',
    },
};

Just filter the dropDownOptions before mapping them to the span elements.

also, if the list of dropDownOptions is ever going to change then use setState else just leave it as a simple list. If dropDownOptions comes from an api call, then use setState within the useEffect hook.


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
thumb_up_alt 0 like thumb_down_alt 0 dislike
Welcome to ShenZhenJia Knowledge Sharing Community for programmer and developer-Open, Learning and Share
...