Follow

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use
Contact

How can I set a Boolean variable's value with a delay, in this React 18 app?

I am making a chat application with Firebase 9 and React 18.

I run into a problem while making use of the OutsideClickHandler package.

In the SearchUsers.jsx component, I have a search-box:

MEDevel.com: Open-source for Healthcare and Education

Collecting and validating open-source software for healthcare, education, enterprise, development, medical imaging, medical records, and digital pathology.

Visit Medevel

import OutsideClickHandler from 'react-outside-click-handler';
export default function SearchUsers({ setIsSearch, setSearchQuery }) {

  const sendSearchQuery = async (e) => {
    if (e.target.value.length > 2) {
      setIsSearch(true);
      setSearchQuery(e.target.value);
    } else {
      if(!e.target.value.length){
        setIsSearch(false);
      }
      setSearchQuery("");
    }
  }

  const handleOutsideClick = () => {
    setTimeout(setIsSearch(false), 200);
  }

  return (
    <OutsideClickHandler onOutsideClick={ handleOutsideClick }>
      <div className="search-box">
        <form className="d-flex">
          <button className="search-button text-muted">
            <FontAwesomeIcon icon="fa-search"/>
          </button>
          <input type="search" placeholder="Find people to talk to" className="search-field w-100" onFocus={() => setIsSearch(true)} onChange={ sendSearchQuery } />
        </form>
      </div>
    </OutsideClickHandler>
  );
}

The above sets the variable isSearch to false when the user clicks outside the search-box.

In UsersList.jsx I have:

import { useLocation } from 'react-router-dom';
import { useEffect, useState } from 'react';
import { or, collection, query, limit, where, getDocs } from "firebase/firestore";
import { db } from "../../firebaseConfig";
import ConversationsList from './ConversationsList';
import UserItem from './UserItem';

export default function UsersList({ isSearch, searchQuery }) {

  const location = useLocation();
  const [users, setUsers] = useState([]);
  const [err, setErr] = useState(false);

  const searchUsers = async () => {

    const q = query(collection(db, "users"),
      or(
        where('firstName', '==', searchQuery),
        where('lastName', '==', searchQuery),
        where('email', '==', searchQuery)
      ), limit(10));

    try {
      const querySnapshot = await getDocs(q);
      const usersArray = [];
      querySnapshot.forEach(doc => {
        if (doc.data() !== null) {
          usersArray.push(doc.data());
        }
      });
      setUsers(usersArray);
    } catch (error) {
      setErr(true);
    }
  }

  const selectUser = (user) => {
    console.log(user);
  }

  const usersList = () => {
    return users.map(user => (
      <UserItem
        key={user.uid}
        user={user}
        selectUser={selectUser}
      />
    ))
  }

  useEffect(() => {
    searchUsers();
  }, [location, setUsers, searchUsers])

  return (
    <>
      {isSearch ?
        <div className="chat-users">
          {!users.length ? <p className="m-0 text-center text-danger">No users found</p> :
            <PerfectScrollbar>
              <ul className="list list-unstyled m-0 d-table w-100">
                {usersList()}
              </ul>
            </PerfectScrollbar>
          }
        </div> : <ConversationsList />
      }
    </>
  );
}

The goal

The goal is to set the isSearch variable to false upon clicking outside the search-box with a delay, so that I can get the selected user (in the Crome console, for now, as seen below):

const selectUser = (user) => {
    console.log(user);
}
    
    

The problem

There is no delay, even though I do use setTimeout. Before introducing the OutsideClickHandler package into the app, I did get the user object, but not anymore. And I need it.

Question:

How can I get the user object while keeping the OutsideClickHandler package?

>Solution :

setTimeout function expects a function as its first argument, but you’re directly calling setIsSearch(false). As a result it’s immediately executed, without any delay. So you need to pass a function to setTimeout:

const handleOutsideClick = () => {
    setTimeout(() => setIsSearch(false), 200);
};
Add a comment

Leave a Reply

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use

Discover more from Dev solutions

Subscribe now to keep reading and get access to the full archive.

Continue reading