Use useEffect to manage the state in React

I wrote a program that takes and displays contacts from an array, and we have an input for searching between contacts, which we type and display the result. I used if in the search function to check if the searchKeyword changes, remember to do the filter else, it did not change, return contacts and no filter is done I want to do this control with useEffect and I commented on the part I wrote with useEffect. Please help me to reach the solution of using useEffect. Thank you.

In fact, I want to use useEffect instead of if

I put my code in the link below

https://codesandbox.io/s/simple-child-parent-comp-forked-4qf39?file=/src/App.js:905-913

1 answer

  • answered 2021-06-23 07:13 Drew Reese

    Issue

    In the useEffect hook in your sandbox you aren't actually updating any state.

    useEffect(()=>{
      const handleFilterContact = () => {
        return contacts.filter((contact) =>
          contact.fullName.toLowerCase().includes(searchKeyword.toLowerCase())
        );
      };
      return () => contacts;
    },[searchKeyword]);
    

    You are returning a value from the useEffect hook which is interpreted by React to be a hook cleanup function.

    See Cleaning up an effect

    Solution

    Add state to MainContent to hold filtered contacts array. Pass the filtered state to the Contact component. You can use the same handleFilterContact function to compute the filtered state.

    const MainContent = ({ contacts }) => {
      const [searchKeyword, setSearchKeyword] = useState("");
      const [filtered, setFiltered] = useState(contacts.slice());
    
      const setValueSearch = (e) => setSearchKeyword(e.target.value);
    
      useEffect(() => {
        const handleFilterContact = () => {
          if (searchKeyword.length >= 1) {
            return contacts.filter((contact) =>
              contact.fullName.toLowerCase().includes(searchKeyword.toLowerCase())
            );
          } else {
            return contacts;
          }
        };
    
        setFiltered(handleFilterContact());
      }, [contacts, searchKeyword]);
    
      return (
        <div>
          <input
            placeholder="Enter a keyword to search"
            onChange={setValueSearch}
          />
          <Contact contacts={contacts} filter={filtered} />
        </div>
      );
    };
    

    Edit use-useeffect-to-manage-the-state-in-react

    Suggestion

    I would recommend against storing a filtered contacts array in state since it is easily derived from the passed contacts prop and the local searchKeyword state. You can filter inline.

    const MainContent = ({ contacts }) => {
      const [searchKeyword, setSearchKeyword] = useState("");
    
      const setValueSearch = (e) => setSearchKeyword(e.target.value);
    
      const filterContact = (contact) => {
        if (searchKeyword.length >= 1) {
          return contact.fullName
            .toLowerCase()
            .includes(searchKeyword.toLowerCase());
        }
        return true;
      };
    
      return (
        <div>
          <input
            placeholder="Enter a keyword to search"
            onChange={setValueSearch}
          />
          <Contact contacts={contacts.filter(filterContact)} />
        </div>
      );
    };