skip to Main Content

I would like a callback function to also execute event.stopPropagation() on the div element where it is being called in addition to updating the state. QueryInput is the customized input div element where user can add text. I want the cursor to retain the focus in the QueryInput when tab key is pressed. Hence, will add stopPropagation() and preventDefault functions. Is it possible to pass event object as a second parameter ?
I tried passing it, but it is not being recognized.

const handleQueryChange = useCallback(
    (q,e) => {
      e.stopPropagation();
      e.preventDefault();
      updateModel({
        ...model,
        query: q
      });
    },
    [updateModel, model]
  );

The call to the callback function is being made it another file

<QueryInput
  id="queryText"
  query={query || ""}
  setSearchQuery={(q, event) => handleQueryChange(q, event)}
>

I get Cannot read properties of undefined (reading ‘stopPropagation’) error when I try to do so.
How do I pass event object as a parameter ?
Without event object, I just call the function as

setSearchQuery={handleQueryChange}

4

Answers


  1. This is how to pass the handleQueryChange function to QueryInput as setSearchQuery:

    <QueryInput
      id="queryText"
      query={query || ""}
      setSearchQuery={handleQueryChange}
    />
    

    and update it like this, the function needs only the event object and from this latter you can retrive the value of the input

    const handleQueryChange = useCallback(
      (e) => {
        e.stopPropagation();
        e.preventDefault();
        updateModel({
          ...model,
          query: e.target.value,
        });
      },
      [updateModel, model]
    )
    

    Then from QueryInput you call it this way :

    const QueryInput = ({ id, query, setSearchQuery }) => {
      //...
      return (
        //...
        <input
          onChange={(event) => {
            setSearchQuery(event);
          }}
        />
      );
    }
    
    Login or Signup to reply.
  2. Found from https://stackoverflow.com/a/72290748/10562084

    const App = () => {
        const [name, setName] = React.useState('John');
    
        const handleQueryChange = React.useCallback((e) => {
            e.stopPropagation();
            e.preventDefault();
            setName(e.currentTarget.value);
          },
          [name]);
    
        return (
            <div>
                <h1>name: {name}</h1>
                <input placeholder='name' onChange={handleQueryChange} />
            </div>
        )
    }
    
    ReactDOM.render(
      <App />,
      document.getElementById('root')
    );
    <script src="https://unpkg.com/[email protected]/umd/react.development.js"></script>
    <script src="https://unpkg.com/[email protected]/umd/react-dom.development.js"></script>
    <div id="root"></div>
    Login or Signup to reply.
  3. Firstly, QueryInput is your component, it is not a native HTML element. Similarly, the setSearchQuery function is also defined by you. Your problem has to be fixed at the place where you are utilizing the native element’s events.

    e.g.,

    <input onChange={(e)=> setSearchQuery(yourData, e)} />
    
    Login or Signup to reply.
  4. Here are some common patterns in vanilla JavaScript though:

    document.addEventListener(‘click’, function(event) { callback(event, x, y) })
    

    // or in arrow form and maybe a scenario where the event object isn’t needed

    document.addEventListener(‘click’, () => callback(props) )
    

    In React, not vanilla JS, the above implementation can be added as an event listener using the useEffect hook (from react api) and passing in the addEventListener function as a dependency. we first define a new function handleClick that calls callback with the props object as an argument. Then, we use the useEffect hook to add an event listener to the document object that listens for the click event and calls our handleClick function when it occurs.

    The useEffect hook also returns a cleanup function that removes the event listener when the component is unmounted or when the callback or props values change, to avoid memory leaks. So you dont need to worry about target and stopPropagation etc, as its covered for you in the useEffect hook (from react api).

    Note the callback at the bottom in the array with the props:

    import { useEffect } from 'react';
    
    function YourComponent(props) {
      useEffect(() => {
        const handleClick = () => {
          callback(props);
        };
    
        document.addEventListener('click', handleClick);
    
        return () => {
          document.removeEventListener('click', handleClick);
        };
      }, [callback, props]);
    
      return null; // or your component JSX
    }
    
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search