How to register event with useEffect hooks? The 2019 Stack Overflow Developer Survey Results Are In Announcing the arrival of Valued Associate #679: Cesar Manara Planned maintenance scheduled April 17/18, 2019 at 00:00UTC (8:00pm US/Eastern) The Ask Question Wizard is Live! Data science time! April 2019 and salary with experienceHow do JavaScript closures work?How do I check if an element is hidden in jQuery?How do I remove a property from a JavaScript object?How do I redirect to another webpage?How do I include a JavaScript file in another JavaScript file?How to replace all occurrences of a string in JavaScriptHow to check whether a string contains a substring in JavaScript?How do I remove a particular element from an array in JavaScript?For-each over an array in JavaScript?How do I return the response from an asynchronous call?

What can I do if neighbor is blocking my solar panels intentionally?

how can a perfect fourth interval be considered either consonant or dissonant?

How do you keep chess fun when your opponent constantly beats you?

Make it rain characters

Variable with quotation marks "$()"

"is" operation returns false even though two objects have same id

Why doesn't shell automatically fix "useless use of cat"?

How many cones with angle theta can I pack into the unit sphere?

Is every episode of "Where are my Pants?" identical?

Why are PDP-7-style microprogrammed instructions out of vogue?

Why not take a picture of a closer black hole?

How to make Illustrator type tool selection automatically adapt with text length

Is there a writing software that you can sort scenes like slides in PowerPoint?

Student Loan from years ago pops up and is taking my salary

Do working physicists consider Newtonian mechanics to be "falsified"?

Was credit for the black hole image misappropriated?

Simulating Exploding Dice

Do ℕ, mathbbN, BbbN, symbbN effectively differ, and is there a "canonical" specification of the naturals?

should truth entail possible truth

Is it ethical to upload a automatically generated paper to a non peer-reviewed site as part of a larger research?

Why can't devices on different VLANs, but on the same subnet, communicate?

Python - Fishing Simulator

Does Parliament need to approve the new Brexit delay to 31 October 2019?

How to read αἱμύλιος or when to aspirate



How to register event with useEffect hooks?



The 2019 Stack Overflow Developer Survey Results Are In
Announcing the arrival of Valued Associate #679: Cesar Manara
Planned maintenance scheduled April 17/18, 2019 at 00:00UTC (8:00pm US/Eastern)
The Ask Question Wizard is Live!
Data science time! April 2019 and salary with experienceHow do JavaScript closures work?How do I check if an element is hidden in jQuery?How do I remove a property from a JavaScript object?How do I redirect to another webpage?How do I include a JavaScript file in another JavaScript file?How to replace all occurrences of a string in JavaScriptHow to check whether a string contains a substring in JavaScript?How do I remove a particular element from an array in JavaScript?For-each over an array in JavaScript?How do I return the response from an asynchronous call?



.everyoneloves__top-leaderboard:empty,.everyoneloves__mid-leaderboard:empty,.everyoneloves__bot-mid-leaderboard:empty height:90px;width:728px;box-sizing:border-box;








8















I am following a Udemy course on how to register events with hooks, the instructor gave the below code:



 const [userText, setUserText] = useState('');

const handleUserKeyPress = event => (keyCode >= 65 && keyCode <= 90))
setUserText(`$userText$key`);

;

useEffect(() =>
window.addEventListener('keydown', handleUserKeyPress);

return () =>
window.removeEventListener('keydown', handleUserKeyPress);
;
);

return (
<div>
<h1>Feel free to type!</h1>
<blockquote>userText</blockquote>
</div>
);


Now it works great but I'm not convinced that this is the right way. The reason is, if I understand correctly, on each and every re-render, events will keep registering and deregistering every time and I simply don't think it is the right way to go about it.



So I made a slight modification to the useEffect hooks to below



useEffect(() => 
window.addEventListener('keydown', handleUserKeyPress);

return () =>
window.removeEventListener('keydown', handleUserKeyPress);
;
, []);


By having an empty array as the second argument, letting the component to only run the effect once, imitating componentDidMount. And when I try out the result, it's weird that on every key I type, instead of appending, it's overwritten instead.



I was expecting setUserText($userText$key); to have new typed key append to current state and set as a new state but instead, it's forgetting the old state and rewriting with the new state.



Was it really the correct way that we should register and deregister event on every re-render?










share|improve this question






























    8















    I am following a Udemy course on how to register events with hooks, the instructor gave the below code:



     const [userText, setUserText] = useState('');

    const handleUserKeyPress = event => (keyCode >= 65 && keyCode <= 90))
    setUserText(`$userText$key`);

    ;

    useEffect(() =>
    window.addEventListener('keydown', handleUserKeyPress);

    return () =>
    window.removeEventListener('keydown', handleUserKeyPress);
    ;
    );

    return (
    <div>
    <h1>Feel free to type!</h1>
    <blockquote>userText</blockquote>
    </div>
    );


    Now it works great but I'm not convinced that this is the right way. The reason is, if I understand correctly, on each and every re-render, events will keep registering and deregistering every time and I simply don't think it is the right way to go about it.



    So I made a slight modification to the useEffect hooks to below



    useEffect(() => 
    window.addEventListener('keydown', handleUserKeyPress);

    return () =>
    window.removeEventListener('keydown', handleUserKeyPress);
    ;
    , []);


    By having an empty array as the second argument, letting the component to only run the effect once, imitating componentDidMount. And when I try out the result, it's weird that on every key I type, instead of appending, it's overwritten instead.



    I was expecting setUserText($userText$key); to have new typed key append to current state and set as a new state but instead, it's forgetting the old state and rewriting with the new state.



    Was it really the correct way that we should register and deregister event on every re-render?










    share|improve this question


























      8












      8








      8


      2






      I am following a Udemy course on how to register events with hooks, the instructor gave the below code:



       const [userText, setUserText] = useState('');

      const handleUserKeyPress = event => (keyCode >= 65 && keyCode <= 90))
      setUserText(`$userText$key`);

      ;

      useEffect(() =>
      window.addEventListener('keydown', handleUserKeyPress);

      return () =>
      window.removeEventListener('keydown', handleUserKeyPress);
      ;
      );

      return (
      <div>
      <h1>Feel free to type!</h1>
      <blockquote>userText</blockquote>
      </div>
      );


      Now it works great but I'm not convinced that this is the right way. The reason is, if I understand correctly, on each and every re-render, events will keep registering and deregistering every time and I simply don't think it is the right way to go about it.



      So I made a slight modification to the useEffect hooks to below



      useEffect(() => 
      window.addEventListener('keydown', handleUserKeyPress);

      return () =>
      window.removeEventListener('keydown', handleUserKeyPress);
      ;
      , []);


      By having an empty array as the second argument, letting the component to only run the effect once, imitating componentDidMount. And when I try out the result, it's weird that on every key I type, instead of appending, it's overwritten instead.



      I was expecting setUserText($userText$key); to have new typed key append to current state and set as a new state but instead, it's forgetting the old state and rewriting with the new state.



      Was it really the correct way that we should register and deregister event on every re-render?










      share|improve this question
















      I am following a Udemy course on how to register events with hooks, the instructor gave the below code:



       const [userText, setUserText] = useState('');

      const handleUserKeyPress = event => (keyCode >= 65 && keyCode <= 90))
      setUserText(`$userText$key`);

      ;

      useEffect(() =>
      window.addEventListener('keydown', handleUserKeyPress);

      return () =>
      window.removeEventListener('keydown', handleUserKeyPress);
      ;
      );

      return (
      <div>
      <h1>Feel free to type!</h1>
      <blockquote>userText</blockquote>
      </div>
      );


      Now it works great but I'm not convinced that this is the right way. The reason is, if I understand correctly, on each and every re-render, events will keep registering and deregistering every time and I simply don't think it is the right way to go about it.



      So I made a slight modification to the useEffect hooks to below



      useEffect(() => 
      window.addEventListener('keydown', handleUserKeyPress);

      return () =>
      window.removeEventListener('keydown', handleUserKeyPress);
      ;
      , []);


      By having an empty array as the second argument, letting the component to only run the effect once, imitating componentDidMount. And when I try out the result, it's weird that on every key I type, instead of appending, it's overwritten instead.



      I was expecting setUserText($userText$key); to have new typed key append to current state and set as a new state but instead, it's forgetting the old state and rewriting with the new state.



      Was it really the correct way that we should register and deregister event on every re-render?







      javascript reactjs react-hooks






      share|improve this question















      share|improve this question













      share|improve this question




      share|improve this question








      edited Apr 8 at 12:25









      John Kennedy

      3,04821329




      3,04821329










      asked Apr 8 at 2:19









      IsaacIsaac

      3,8192830




      3,8192830






















          6 Answers
          6






          active

          oldest

          votes


















          6














          The best way to go about such scenarios is to see what you are doing in the event handler. If you are simply setting state using previous state, its best to use the callback pattern and register the event listeners only on initial mount. If you do not use the callback pattern (https://reactjs.org/docs/hooks-reference.html#usecallback) the listeners reference along with its lexical scope is being used by the event listener but a new function is created with updated closure on new render and hence in the handler you will not be able to the updated state



          const [userText, setUserText] = useState('');

          const handleUserKeyPress = useCallback(event =>
          const key, keyCode = event;

          if (keyCode === 32 , []);

          useEffect(() =>
          window.addEventListener('keydown', handleUserKeyPress);

          return () =>
          window.removeEventListener('keydown', handleUserKeyPress);
          ;
          , [handleUserKeyPress]);

          return (
          <div>
          <h1>Feel free to type!</h1>
          <blockquote>userText</blockquote>
          </div>
          );





          share|improve this answer

























          • Your solution makes most sense to me as compared to others, thanks a lot!

            – Isaac
            Apr 8 at 5:27











          • Glad to have helped (y)

            – Shubham Khatri
            Apr 8 at 6:06











          • but this will create a new bound function every keypress. if your focus is perfromance a local state variable is much better

            – di3
            Apr 8 at 8:51











          • @di3 If you use useCallback to define the function with empty dependency array, you won't have that issue as well

            – Shubham Khatri
            Apr 8 at 10:00











          • yes that would work too. just wanted to point it out

            – di3
            Apr 8 at 10:16


















          1














          For your use case, useEffect needs a dependency array to track changes and based on the dependency it can determine whether to re-render or not. It is always advised to pass a dependency array to useEffect. Kindly see the code below:



          I have introduced useCallback hook.



          const useCallback, useState, useEffect = React;

          const [userText, setUserText] = useState("");

          const handleUserKeyPress = useCallback(event =>
          const key, keyCode = event;

          if (keyCode === 32 , []);

          useEffect(() =>
          window.addEventListener("keydown", handleUserKeyPress);

          return () =>
          window.removeEventListener("keydown", handleUserKeyPress);
          ;
          , [handleUserKeyPress]);

          return (
          <div>
          <blockquote>userText</blockquote>
          </div>
          );


          Edit q98jov5kvq






          share|improve this answer

























          • I've tried your solution, but it's exactly the same as [userText] or without second argument. Basically we put a console.log inside useEffect, we will see that the logging is firing every re-render, which also means, addEventListender is running every re-render

            – Isaac
            Apr 8 at 3:26












          • I want to believe that is an expected behaviour. I updated my answer.

            – John Kennedy
            Apr 8 at 3:39











          • On your sandbox, you've put a statement console.log('>'); within useEffect hooks, and by using your updated code, it's still logging everytime, which also means the events are still registering on every re-render

            – Isaac
            Apr 8 at 3:45






          • 1





            but because of return () => window.removeEventListener('keydown', handleUserKeyPress), on every re-render, the component will register and deregister

            – Isaac
            Apr 8 at 4:00






          • 1





            Exactly the behaviour that I wished for, but you can observe it @ codesandbox.io/s/n5j7qy051j

            – Isaac
            Apr 8 at 4:06


















          1














          new answer:



          useEffect(() => 
          function handlekeydownEvent(event) (keyCode >= 65 && keyCode <= 90))
          setUserText(prevUserText => `$prevUserText$key`);



          document.addEventListener('keyup', handlekeydownEvent)
          return () =>
          document.removeEventListener('keyup', handlekeydownEvent)

          , [])


          when using setUserText, pass the function as the argument instead of the object, the prevUserText will be always the newest state.




          old answer:



          try this, it works same as your original code:



          useEffect(() => 
          function handlekeydownEvent(event)
          const key, keyCode = event;
          if (keyCode === 32

          document.addEventListener('keyup', handlekeydownEvent)
          return () =>
          document.removeEventListener('keyup', handlekeydownEvent)

          , [userText])


          because in your useEffect() method, it depends on the userText variable but you don't put it inside the second argument, else the userText will always be bound to the initial value '' with argument [].



          you don't need to do like this, just want to let you know why your second solution doesn't work.






          share|improve this answer

























          • By adding [userText] is exactly the same as without second argument, right? Reason is I only have userText in the above example, and without second argument simply means re-rerender on every props/state changes, I don't see how it answer my question. **P/S: ** I'm not the downvoter, thanks for your answer anyway

            – Isaac
            Apr 8 at 2:53












          • hey @Isaac , yep, it is same as without second argument, I just want to let you know why your second solution doesn't work, because your second solution useEffect() depend on the userText variable but you didn't put inside the second arguments.

            – Spark.Bao
            Apr 8 at 3:08












          • But by adding in [userText], it also means register and deregister the event on every re-render right?

            – Isaac
            Apr 8 at 3:14











          • exactly! that why I say it is same with your first solution.

            – Spark.Bao
            Apr 8 at 3:17






          • 1





            got what you mean, if you really want to register it only one time in this example, then you need to use useRef, just as @Maaz Syed Adeeb 's answer.

            – Spark.Bao
            Apr 8 at 3:23



















          0














          You'll need a way to keep track of the previous state. useState helps you keep track of the current state only. From the docs, there is a way to access the old state, by using another hook.



          const prevRef = useRef();
          useEffect(() =>
          prevRef.current = userText;
          );


          I've updated your example to use this. And it works out.






          const useState, useEffect, useRef = React;

          const App = () =>
          const [userText, setUserText] = useState("");
          const prevRef = useRef();
          useEffect(() =>
          prevRef.current = userText;
          );

          const handleUserKeyPress = event => (keyCode >= 65 && keyCode <= 90))
          setUserText(`$prevRef.current$key`);

          ;

          useEffect(() =>
          window.addEventListener("keydown", handleUserKeyPress);

          return () =>
          window.removeEventListener("keydown", handleUserKeyPress);
          ;
          , []);

          return (
          <div>
          <h1>Feel free to type!</h1>
          <blockquote>userText</blockquote>
          </div>
          );
          ;

          ReactDOM.render(<App />, document.getElementById("root"));

          <script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.8.3/umd/react.production.min.js"></script>
          <script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.8.3/umd/react-dom.production.min.js"></script>
          <div id="root"></div>








          share|improve this answer






























            -1














            In the second approach, the useEffect is bound only once and hence the userText never gets updated. One approach would be to maintain a local variable which gets updated along with the userText object on every keypress.



             const [userText, setUserText] = useState('');
            let local_text = userText
            const handleUserKeyPress = event => ;

            useEffect(() =>
            window.addEventListener('keydown', handleUserKeyPress);

            return () =>
            window.removeEventListener('keydown', handleUserKeyPress);
            ;
            , []);

            return (
            <div>
            <h1>Feel free to type!</h1>
            <blockquote>userText</blockquote>
            </div>
            );


            Personally I don't like the solution, feels anti-react and I think the first method is good enough and is designed to be used that way.






            share|improve this answer

























            • Do you mind to include some code to demonstrate how to achieve my objective in second method?

              – Isaac
              Apr 8 at 2:51


















            -1














            you dont have access to the changed useText state. you can comapre it to the prevState. store the state in a variable e.g.: state like so:



            const App = () => 
            const [userText, setUserText] = useState('');

            useEffect(() =>
            let state = ''

            const handleUserKeyPress = event => ;
            window.addEventListener('keydown', handleUserKeyPress);
            return () =>
            window.removeEventListener('keydown', handleUserKeyPress);
            ;
            , []);

            return (
            <div>
            <h1>Feel free to type!</h1>
            <blockquote>userText</blockquote>
            </div>
            );
            ;





            share|improve this answer

























              Your Answer






              StackExchange.ifUsing("editor", function ()
              StackExchange.using("externalEditor", function ()
              StackExchange.using("snippets", function ()
              StackExchange.snippets.init();
              );
              );
              , "code-snippets");

              StackExchange.ready(function()
              var channelOptions =
              tags: "".split(" "),
              id: "1"
              ;
              initTagRenderer("".split(" "), "".split(" "), channelOptions);

              StackExchange.using("externalEditor", function()
              // Have to fire editor after snippets, if snippets enabled
              if (StackExchange.settings.snippets.snippetsEnabled)
              StackExchange.using("snippets", function()
              createEditor();
              );

              else
              createEditor();

              );

              function createEditor()
              StackExchange.prepareEditor(
              heartbeatType: 'answer',
              autoActivateHeartbeat: false,
              convertImagesToLinks: true,
              noModals: true,
              showLowRepImageUploadWarning: true,
              reputationToPostImages: 10,
              bindNavPrevention: true,
              postfix: "",
              imageUploader:
              brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
              contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
              allowUrls: true
              ,
              onDemand: true,
              discardSelector: ".discard-answer"
              ,immediatelyShowMarkdownHelp:true
              );



              );













              draft saved

              draft discarded


















              StackExchange.ready(
              function ()
              StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f55565444%2fhow-to-register-event-with-useeffect-hooks%23new-answer', 'question_page');

              );

              Post as a guest















              Required, but never shown

























              6 Answers
              6






              active

              oldest

              votes








              6 Answers
              6






              active

              oldest

              votes









              active

              oldest

              votes






              active

              oldest

              votes









              6














              The best way to go about such scenarios is to see what you are doing in the event handler. If you are simply setting state using previous state, its best to use the callback pattern and register the event listeners only on initial mount. If you do not use the callback pattern (https://reactjs.org/docs/hooks-reference.html#usecallback) the listeners reference along with its lexical scope is being used by the event listener but a new function is created with updated closure on new render and hence in the handler you will not be able to the updated state



              const [userText, setUserText] = useState('');

              const handleUserKeyPress = useCallback(event =>
              const key, keyCode = event;

              if (keyCode === 32 , []);

              useEffect(() =>
              window.addEventListener('keydown', handleUserKeyPress);

              return () =>
              window.removeEventListener('keydown', handleUserKeyPress);
              ;
              , [handleUserKeyPress]);

              return (
              <div>
              <h1>Feel free to type!</h1>
              <blockquote>userText</blockquote>
              </div>
              );





              share|improve this answer

























              • Your solution makes most sense to me as compared to others, thanks a lot!

                – Isaac
                Apr 8 at 5:27











              • Glad to have helped (y)

                – Shubham Khatri
                Apr 8 at 6:06











              • but this will create a new bound function every keypress. if your focus is perfromance a local state variable is much better

                – di3
                Apr 8 at 8:51











              • @di3 If you use useCallback to define the function with empty dependency array, you won't have that issue as well

                – Shubham Khatri
                Apr 8 at 10:00











              • yes that would work too. just wanted to point it out

                – di3
                Apr 8 at 10:16















              6














              The best way to go about such scenarios is to see what you are doing in the event handler. If you are simply setting state using previous state, its best to use the callback pattern and register the event listeners only on initial mount. If you do not use the callback pattern (https://reactjs.org/docs/hooks-reference.html#usecallback) the listeners reference along with its lexical scope is being used by the event listener but a new function is created with updated closure on new render and hence in the handler you will not be able to the updated state



              const [userText, setUserText] = useState('');

              const handleUserKeyPress = useCallback(event =>
              const key, keyCode = event;

              if (keyCode === 32 , []);

              useEffect(() =>
              window.addEventListener('keydown', handleUserKeyPress);

              return () =>
              window.removeEventListener('keydown', handleUserKeyPress);
              ;
              , [handleUserKeyPress]);

              return (
              <div>
              <h1>Feel free to type!</h1>
              <blockquote>userText</blockquote>
              </div>
              );





              share|improve this answer

























              • Your solution makes most sense to me as compared to others, thanks a lot!

                – Isaac
                Apr 8 at 5:27











              • Glad to have helped (y)

                – Shubham Khatri
                Apr 8 at 6:06











              • but this will create a new bound function every keypress. if your focus is perfromance a local state variable is much better

                – di3
                Apr 8 at 8:51











              • @di3 If you use useCallback to define the function with empty dependency array, you won't have that issue as well

                – Shubham Khatri
                Apr 8 at 10:00











              • yes that would work too. just wanted to point it out

                – di3
                Apr 8 at 10:16













              6












              6








              6







              The best way to go about such scenarios is to see what you are doing in the event handler. If you are simply setting state using previous state, its best to use the callback pattern and register the event listeners only on initial mount. If you do not use the callback pattern (https://reactjs.org/docs/hooks-reference.html#usecallback) the listeners reference along with its lexical scope is being used by the event listener but a new function is created with updated closure on new render and hence in the handler you will not be able to the updated state



              const [userText, setUserText] = useState('');

              const handleUserKeyPress = useCallback(event =>
              const key, keyCode = event;

              if (keyCode === 32 , []);

              useEffect(() =>
              window.addEventListener('keydown', handleUserKeyPress);

              return () =>
              window.removeEventListener('keydown', handleUserKeyPress);
              ;
              , [handleUserKeyPress]);

              return (
              <div>
              <h1>Feel free to type!</h1>
              <blockquote>userText</blockquote>
              </div>
              );





              share|improve this answer















              The best way to go about such scenarios is to see what you are doing in the event handler. If you are simply setting state using previous state, its best to use the callback pattern and register the event listeners only on initial mount. If you do not use the callback pattern (https://reactjs.org/docs/hooks-reference.html#usecallback) the listeners reference along with its lexical scope is being used by the event listener but a new function is created with updated closure on new render and hence in the handler you will not be able to the updated state



              const [userText, setUserText] = useState('');

              const handleUserKeyPress = useCallback(event =>
              const key, keyCode = event;

              if (keyCode === 32 , []);

              useEffect(() =>
              window.addEventListener('keydown', handleUserKeyPress);

              return () =>
              window.removeEventListener('keydown', handleUserKeyPress);
              ;
              , [handleUserKeyPress]);

              return (
              <div>
              <h1>Feel free to type!</h1>
              <blockquote>userText</blockquote>
              </div>
              );






              share|improve this answer














              share|improve this answer



              share|improve this answer








              edited Apr 8 at 17:33

























              answered Apr 8 at 5:08









              Shubham KhatriShubham Khatri

              96.5k15123163




              96.5k15123163












              • Your solution makes most sense to me as compared to others, thanks a lot!

                – Isaac
                Apr 8 at 5:27











              • Glad to have helped (y)

                – Shubham Khatri
                Apr 8 at 6:06











              • but this will create a new bound function every keypress. if your focus is perfromance a local state variable is much better

                – di3
                Apr 8 at 8:51











              • @di3 If you use useCallback to define the function with empty dependency array, you won't have that issue as well

                – Shubham Khatri
                Apr 8 at 10:00











              • yes that would work too. just wanted to point it out

                – di3
                Apr 8 at 10:16

















              • Your solution makes most sense to me as compared to others, thanks a lot!

                – Isaac
                Apr 8 at 5:27











              • Glad to have helped (y)

                – Shubham Khatri
                Apr 8 at 6:06











              • but this will create a new bound function every keypress. if your focus is perfromance a local state variable is much better

                – di3
                Apr 8 at 8:51











              • @di3 If you use useCallback to define the function with empty dependency array, you won't have that issue as well

                – Shubham Khatri
                Apr 8 at 10:00











              • yes that would work too. just wanted to point it out

                – di3
                Apr 8 at 10:16
















              Your solution makes most sense to me as compared to others, thanks a lot!

              – Isaac
              Apr 8 at 5:27





              Your solution makes most sense to me as compared to others, thanks a lot!

              – Isaac
              Apr 8 at 5:27













              Glad to have helped (y)

              – Shubham Khatri
              Apr 8 at 6:06





              Glad to have helped (y)

              – Shubham Khatri
              Apr 8 at 6:06













              but this will create a new bound function every keypress. if your focus is perfromance a local state variable is much better

              – di3
              Apr 8 at 8:51





              but this will create a new bound function every keypress. if your focus is perfromance a local state variable is much better

              – di3
              Apr 8 at 8:51













              @di3 If you use useCallback to define the function with empty dependency array, you won't have that issue as well

              – Shubham Khatri
              Apr 8 at 10:00





              @di3 If you use useCallback to define the function with empty dependency array, you won't have that issue as well

              – Shubham Khatri
              Apr 8 at 10:00













              yes that would work too. just wanted to point it out

              – di3
              Apr 8 at 10:16





              yes that would work too. just wanted to point it out

              – di3
              Apr 8 at 10:16













              1














              For your use case, useEffect needs a dependency array to track changes and based on the dependency it can determine whether to re-render or not. It is always advised to pass a dependency array to useEffect. Kindly see the code below:



              I have introduced useCallback hook.



              const useCallback, useState, useEffect = React;

              const [userText, setUserText] = useState("");

              const handleUserKeyPress = useCallback(event =>
              const key, keyCode = event;

              if (keyCode === 32 , []);

              useEffect(() =>
              window.addEventListener("keydown", handleUserKeyPress);

              return () =>
              window.removeEventListener("keydown", handleUserKeyPress);
              ;
              , [handleUserKeyPress]);

              return (
              <div>
              <blockquote>userText</blockquote>
              </div>
              );


              Edit q98jov5kvq






              share|improve this answer

























              • I've tried your solution, but it's exactly the same as [userText] or without second argument. Basically we put a console.log inside useEffect, we will see that the logging is firing every re-render, which also means, addEventListender is running every re-render

                – Isaac
                Apr 8 at 3:26












              • I want to believe that is an expected behaviour. I updated my answer.

                – John Kennedy
                Apr 8 at 3:39











              • On your sandbox, you've put a statement console.log('>'); within useEffect hooks, and by using your updated code, it's still logging everytime, which also means the events are still registering on every re-render

                – Isaac
                Apr 8 at 3:45






              • 1





                but because of return () => window.removeEventListener('keydown', handleUserKeyPress), on every re-render, the component will register and deregister

                – Isaac
                Apr 8 at 4:00






              • 1





                Exactly the behaviour that I wished for, but you can observe it @ codesandbox.io/s/n5j7qy051j

                – Isaac
                Apr 8 at 4:06















              1














              For your use case, useEffect needs a dependency array to track changes and based on the dependency it can determine whether to re-render or not. It is always advised to pass a dependency array to useEffect. Kindly see the code below:



              I have introduced useCallback hook.



              const useCallback, useState, useEffect = React;

              const [userText, setUserText] = useState("");

              const handleUserKeyPress = useCallback(event =>
              const key, keyCode = event;

              if (keyCode === 32 , []);

              useEffect(() =>
              window.addEventListener("keydown", handleUserKeyPress);

              return () =>
              window.removeEventListener("keydown", handleUserKeyPress);
              ;
              , [handleUserKeyPress]);

              return (
              <div>
              <blockquote>userText</blockquote>
              </div>
              );


              Edit q98jov5kvq






              share|improve this answer

























              • I've tried your solution, but it's exactly the same as [userText] or without second argument. Basically we put a console.log inside useEffect, we will see that the logging is firing every re-render, which also means, addEventListender is running every re-render

                – Isaac
                Apr 8 at 3:26












              • I want to believe that is an expected behaviour. I updated my answer.

                – John Kennedy
                Apr 8 at 3:39











              • On your sandbox, you've put a statement console.log('>'); within useEffect hooks, and by using your updated code, it's still logging everytime, which also means the events are still registering on every re-render

                – Isaac
                Apr 8 at 3:45






              • 1





                but because of return () => window.removeEventListener('keydown', handleUserKeyPress), on every re-render, the component will register and deregister

                – Isaac
                Apr 8 at 4:00






              • 1





                Exactly the behaviour that I wished for, but you can observe it @ codesandbox.io/s/n5j7qy051j

                – Isaac
                Apr 8 at 4:06













              1












              1








              1







              For your use case, useEffect needs a dependency array to track changes and based on the dependency it can determine whether to re-render or not. It is always advised to pass a dependency array to useEffect. Kindly see the code below:



              I have introduced useCallback hook.



              const useCallback, useState, useEffect = React;

              const [userText, setUserText] = useState("");

              const handleUserKeyPress = useCallback(event =>
              const key, keyCode = event;

              if (keyCode === 32 , []);

              useEffect(() =>
              window.addEventListener("keydown", handleUserKeyPress);

              return () =>
              window.removeEventListener("keydown", handleUserKeyPress);
              ;
              , [handleUserKeyPress]);

              return (
              <div>
              <blockquote>userText</blockquote>
              </div>
              );


              Edit q98jov5kvq






              share|improve this answer















              For your use case, useEffect needs a dependency array to track changes and based on the dependency it can determine whether to re-render or not. It is always advised to pass a dependency array to useEffect. Kindly see the code below:



              I have introduced useCallback hook.



              const useCallback, useState, useEffect = React;

              const [userText, setUserText] = useState("");

              const handleUserKeyPress = useCallback(event =>
              const key, keyCode = event;

              if (keyCode === 32 , []);

              useEffect(() =>
              window.addEventListener("keydown", handleUserKeyPress);

              return () =>
              window.removeEventListener("keydown", handleUserKeyPress);
              ;
              , [handleUserKeyPress]);

              return (
              <div>
              <blockquote>userText</blockquote>
              </div>
              );


              Edit q98jov5kvq







              share|improve this answer














              share|improve this answer



              share|improve this answer








              edited Apr 8 at 12:35

























              answered Apr 8 at 3:20









              John KennedyJohn Kennedy

              3,04821329




              3,04821329












              • I've tried your solution, but it's exactly the same as [userText] or without second argument. Basically we put a console.log inside useEffect, we will see that the logging is firing every re-render, which also means, addEventListender is running every re-render

                – Isaac
                Apr 8 at 3:26












              • I want to believe that is an expected behaviour. I updated my answer.

                – John Kennedy
                Apr 8 at 3:39











              • On your sandbox, you've put a statement console.log('>'); within useEffect hooks, and by using your updated code, it's still logging everytime, which also means the events are still registering on every re-render

                – Isaac
                Apr 8 at 3:45






              • 1





                but because of return () => window.removeEventListener('keydown', handleUserKeyPress), on every re-render, the component will register and deregister

                – Isaac
                Apr 8 at 4:00






              • 1





                Exactly the behaviour that I wished for, but you can observe it @ codesandbox.io/s/n5j7qy051j

                – Isaac
                Apr 8 at 4:06

















              • I've tried your solution, but it's exactly the same as [userText] or without second argument. Basically we put a console.log inside useEffect, we will see that the logging is firing every re-render, which also means, addEventListender is running every re-render

                – Isaac
                Apr 8 at 3:26












              • I want to believe that is an expected behaviour. I updated my answer.

                – John Kennedy
                Apr 8 at 3:39











              • On your sandbox, you've put a statement console.log('>'); within useEffect hooks, and by using your updated code, it's still logging everytime, which also means the events are still registering on every re-render

                – Isaac
                Apr 8 at 3:45






              • 1





                but because of return () => window.removeEventListener('keydown', handleUserKeyPress), on every re-render, the component will register and deregister

                – Isaac
                Apr 8 at 4:00






              • 1





                Exactly the behaviour that I wished for, but you can observe it @ codesandbox.io/s/n5j7qy051j

                – Isaac
                Apr 8 at 4:06
















              I've tried your solution, but it's exactly the same as [userText] or without second argument. Basically we put a console.log inside useEffect, we will see that the logging is firing every re-render, which also means, addEventListender is running every re-render

              – Isaac
              Apr 8 at 3:26






              I've tried your solution, but it's exactly the same as [userText] or without second argument. Basically we put a console.log inside useEffect, we will see that the logging is firing every re-render, which also means, addEventListender is running every re-render

              – Isaac
              Apr 8 at 3:26














              I want to believe that is an expected behaviour. I updated my answer.

              – John Kennedy
              Apr 8 at 3:39





              I want to believe that is an expected behaviour. I updated my answer.

              – John Kennedy
              Apr 8 at 3:39













              On your sandbox, you've put a statement console.log('>'); within useEffect hooks, and by using your updated code, it's still logging everytime, which also means the events are still registering on every re-render

              – Isaac
              Apr 8 at 3:45





              On your sandbox, you've put a statement console.log('>'); within useEffect hooks, and by using your updated code, it's still logging everytime, which also means the events are still registering on every re-render

              – Isaac
              Apr 8 at 3:45




              1




              1





              but because of return () => window.removeEventListener('keydown', handleUserKeyPress), on every re-render, the component will register and deregister

              – Isaac
              Apr 8 at 4:00





              but because of return () => window.removeEventListener('keydown', handleUserKeyPress), on every re-render, the component will register and deregister

              – Isaac
              Apr 8 at 4:00




              1




              1





              Exactly the behaviour that I wished for, but you can observe it @ codesandbox.io/s/n5j7qy051j

              – Isaac
              Apr 8 at 4:06





              Exactly the behaviour that I wished for, but you can observe it @ codesandbox.io/s/n5j7qy051j

              – Isaac
              Apr 8 at 4:06











              1














              new answer:



              useEffect(() => 
              function handlekeydownEvent(event) (keyCode >= 65 && keyCode <= 90))
              setUserText(prevUserText => `$prevUserText$key`);



              document.addEventListener('keyup', handlekeydownEvent)
              return () =>
              document.removeEventListener('keyup', handlekeydownEvent)

              , [])


              when using setUserText, pass the function as the argument instead of the object, the prevUserText will be always the newest state.




              old answer:



              try this, it works same as your original code:



              useEffect(() => 
              function handlekeydownEvent(event)
              const key, keyCode = event;
              if (keyCode === 32

              document.addEventListener('keyup', handlekeydownEvent)
              return () =>
              document.removeEventListener('keyup', handlekeydownEvent)

              , [userText])


              because in your useEffect() method, it depends on the userText variable but you don't put it inside the second argument, else the userText will always be bound to the initial value '' with argument [].



              you don't need to do like this, just want to let you know why your second solution doesn't work.






              share|improve this answer

























              • By adding [userText] is exactly the same as without second argument, right? Reason is I only have userText in the above example, and without second argument simply means re-rerender on every props/state changes, I don't see how it answer my question. **P/S: ** I'm not the downvoter, thanks for your answer anyway

                – Isaac
                Apr 8 at 2:53












              • hey @Isaac , yep, it is same as without second argument, I just want to let you know why your second solution doesn't work, because your second solution useEffect() depend on the userText variable but you didn't put inside the second arguments.

                – Spark.Bao
                Apr 8 at 3:08












              • But by adding in [userText], it also means register and deregister the event on every re-render right?

                – Isaac
                Apr 8 at 3:14











              • exactly! that why I say it is same with your first solution.

                – Spark.Bao
                Apr 8 at 3:17






              • 1





                got what you mean, if you really want to register it only one time in this example, then you need to use useRef, just as @Maaz Syed Adeeb 's answer.

                – Spark.Bao
                Apr 8 at 3:23
















              1














              new answer:



              useEffect(() => 
              function handlekeydownEvent(event) (keyCode >= 65 && keyCode <= 90))
              setUserText(prevUserText => `$prevUserText$key`);



              document.addEventListener('keyup', handlekeydownEvent)
              return () =>
              document.removeEventListener('keyup', handlekeydownEvent)

              , [])


              when using setUserText, pass the function as the argument instead of the object, the prevUserText will be always the newest state.




              old answer:



              try this, it works same as your original code:



              useEffect(() => 
              function handlekeydownEvent(event)
              const key, keyCode = event;
              if (keyCode === 32

              document.addEventListener('keyup', handlekeydownEvent)
              return () =>
              document.removeEventListener('keyup', handlekeydownEvent)

              , [userText])


              because in your useEffect() method, it depends on the userText variable but you don't put it inside the second argument, else the userText will always be bound to the initial value '' with argument [].



              you don't need to do like this, just want to let you know why your second solution doesn't work.






              share|improve this answer

























              • By adding [userText] is exactly the same as without second argument, right? Reason is I only have userText in the above example, and without second argument simply means re-rerender on every props/state changes, I don't see how it answer my question. **P/S: ** I'm not the downvoter, thanks for your answer anyway

                – Isaac
                Apr 8 at 2:53












              • hey @Isaac , yep, it is same as without second argument, I just want to let you know why your second solution doesn't work, because your second solution useEffect() depend on the userText variable but you didn't put inside the second arguments.

                – Spark.Bao
                Apr 8 at 3:08












              • But by adding in [userText], it also means register and deregister the event on every re-render right?

                – Isaac
                Apr 8 at 3:14











              • exactly! that why I say it is same with your first solution.

                – Spark.Bao
                Apr 8 at 3:17






              • 1





                got what you mean, if you really want to register it only one time in this example, then you need to use useRef, just as @Maaz Syed Adeeb 's answer.

                – Spark.Bao
                Apr 8 at 3:23














              1












              1








              1







              new answer:



              useEffect(() => 
              function handlekeydownEvent(event) (keyCode >= 65 && keyCode <= 90))
              setUserText(prevUserText => `$prevUserText$key`);



              document.addEventListener('keyup', handlekeydownEvent)
              return () =>
              document.removeEventListener('keyup', handlekeydownEvent)

              , [])


              when using setUserText, pass the function as the argument instead of the object, the prevUserText will be always the newest state.




              old answer:



              try this, it works same as your original code:



              useEffect(() => 
              function handlekeydownEvent(event)
              const key, keyCode = event;
              if (keyCode === 32

              document.addEventListener('keyup', handlekeydownEvent)
              return () =>
              document.removeEventListener('keyup', handlekeydownEvent)

              , [userText])


              because in your useEffect() method, it depends on the userText variable but you don't put it inside the second argument, else the userText will always be bound to the initial value '' with argument [].



              you don't need to do like this, just want to let you know why your second solution doesn't work.






              share|improve this answer















              new answer:



              useEffect(() => 
              function handlekeydownEvent(event) (keyCode >= 65 && keyCode <= 90))
              setUserText(prevUserText => `$prevUserText$key`);



              document.addEventListener('keyup', handlekeydownEvent)
              return () =>
              document.removeEventListener('keyup', handlekeydownEvent)

              , [])


              when using setUserText, pass the function as the argument instead of the object, the prevUserText will be always the newest state.




              old answer:



              try this, it works same as your original code:



              useEffect(() => 
              function handlekeydownEvent(event)
              const key, keyCode = event;
              if (keyCode === 32

              document.addEventListener('keyup', handlekeydownEvent)
              return () =>
              document.removeEventListener('keyup', handlekeydownEvent)

              , [userText])


              because in your useEffect() method, it depends on the userText variable but you don't put it inside the second argument, else the userText will always be bound to the initial value '' with argument [].



              you don't need to do like this, just want to let you know why your second solution doesn't work.







              share|improve this answer














              share|improve this answer



              share|improve this answer








              edited 2 days ago

























              answered Apr 8 at 2:51









              Spark.BaoSpark.Bao

              2,6711830




              2,6711830












              • By adding [userText] is exactly the same as without second argument, right? Reason is I only have userText in the above example, and without second argument simply means re-rerender on every props/state changes, I don't see how it answer my question. **P/S: ** I'm not the downvoter, thanks for your answer anyway

                – Isaac
                Apr 8 at 2:53












              • hey @Isaac , yep, it is same as without second argument, I just want to let you know why your second solution doesn't work, because your second solution useEffect() depend on the userText variable but you didn't put inside the second arguments.

                – Spark.Bao
                Apr 8 at 3:08












              • But by adding in [userText], it also means register and deregister the event on every re-render right?

                – Isaac
                Apr 8 at 3:14











              • exactly! that why I say it is same with your first solution.

                – Spark.Bao
                Apr 8 at 3:17






              • 1





                got what you mean, if you really want to register it only one time in this example, then you need to use useRef, just as @Maaz Syed Adeeb 's answer.

                – Spark.Bao
                Apr 8 at 3:23


















              • By adding [userText] is exactly the same as without second argument, right? Reason is I only have userText in the above example, and without second argument simply means re-rerender on every props/state changes, I don't see how it answer my question. **P/S: ** I'm not the downvoter, thanks for your answer anyway

                – Isaac
                Apr 8 at 2:53












              • hey @Isaac , yep, it is same as without second argument, I just want to let you know why your second solution doesn't work, because your second solution useEffect() depend on the userText variable but you didn't put inside the second arguments.

                – Spark.Bao
                Apr 8 at 3:08












              • But by adding in [userText], it also means register and deregister the event on every re-render right?

                – Isaac
                Apr 8 at 3:14











              • exactly! that why I say it is same with your first solution.

                – Spark.Bao
                Apr 8 at 3:17






              • 1





                got what you mean, if you really want to register it only one time in this example, then you need to use useRef, just as @Maaz Syed Adeeb 's answer.

                – Spark.Bao
                Apr 8 at 3:23

















              By adding [userText] is exactly the same as without second argument, right? Reason is I only have userText in the above example, and without second argument simply means re-rerender on every props/state changes, I don't see how it answer my question. **P/S: ** I'm not the downvoter, thanks for your answer anyway

              – Isaac
              Apr 8 at 2:53






              By adding [userText] is exactly the same as without second argument, right? Reason is I only have userText in the above example, and without second argument simply means re-rerender on every props/state changes, I don't see how it answer my question. **P/S: ** I'm not the downvoter, thanks for your answer anyway

              – Isaac
              Apr 8 at 2:53














              hey @Isaac , yep, it is same as without second argument, I just want to let you know why your second solution doesn't work, because your second solution useEffect() depend on the userText variable but you didn't put inside the second arguments.

              – Spark.Bao
              Apr 8 at 3:08






              hey @Isaac , yep, it is same as without second argument, I just want to let you know why your second solution doesn't work, because your second solution useEffect() depend on the userText variable but you didn't put inside the second arguments.

              – Spark.Bao
              Apr 8 at 3:08














              But by adding in [userText], it also means register and deregister the event on every re-render right?

              – Isaac
              Apr 8 at 3:14





              But by adding in [userText], it also means register and deregister the event on every re-render right?

              – Isaac
              Apr 8 at 3:14













              exactly! that why I say it is same with your first solution.

              – Spark.Bao
              Apr 8 at 3:17





              exactly! that why I say it is same with your first solution.

              – Spark.Bao
              Apr 8 at 3:17




              1




              1





              got what you mean, if you really want to register it only one time in this example, then you need to use useRef, just as @Maaz Syed Adeeb 's answer.

              – Spark.Bao
              Apr 8 at 3:23






              got what you mean, if you really want to register it only one time in this example, then you need to use useRef, just as @Maaz Syed Adeeb 's answer.

              – Spark.Bao
              Apr 8 at 3:23












              0














              You'll need a way to keep track of the previous state. useState helps you keep track of the current state only. From the docs, there is a way to access the old state, by using another hook.



              const prevRef = useRef();
              useEffect(() =>
              prevRef.current = userText;
              );


              I've updated your example to use this. And it works out.






              const useState, useEffect, useRef = React;

              const App = () =>
              const [userText, setUserText] = useState("");
              const prevRef = useRef();
              useEffect(() =>
              prevRef.current = userText;
              );

              const handleUserKeyPress = event => (keyCode >= 65 && keyCode <= 90))
              setUserText(`$prevRef.current$key`);

              ;

              useEffect(() =>
              window.addEventListener("keydown", handleUserKeyPress);

              return () =>
              window.removeEventListener("keydown", handleUserKeyPress);
              ;
              , []);

              return (
              <div>
              <h1>Feel free to type!</h1>
              <blockquote>userText</blockquote>
              </div>
              );
              ;

              ReactDOM.render(<App />, document.getElementById("root"));

              <script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.8.3/umd/react.production.min.js"></script>
              <script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.8.3/umd/react-dom.production.min.js"></script>
              <div id="root"></div>








              share|improve this answer



























                0














                You'll need a way to keep track of the previous state. useState helps you keep track of the current state only. From the docs, there is a way to access the old state, by using another hook.



                const prevRef = useRef();
                useEffect(() =>
                prevRef.current = userText;
                );


                I've updated your example to use this. And it works out.






                const useState, useEffect, useRef = React;

                const App = () =>
                const [userText, setUserText] = useState("");
                const prevRef = useRef();
                useEffect(() =>
                prevRef.current = userText;
                );

                const handleUserKeyPress = event => (keyCode >= 65 && keyCode <= 90))
                setUserText(`$prevRef.current$key`);

                ;

                useEffect(() =>
                window.addEventListener("keydown", handleUserKeyPress);

                return () =>
                window.removeEventListener("keydown", handleUserKeyPress);
                ;
                , []);

                return (
                <div>
                <h1>Feel free to type!</h1>
                <blockquote>userText</blockquote>
                </div>
                );
                ;

                ReactDOM.render(<App />, document.getElementById("root"));

                <script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.8.3/umd/react.production.min.js"></script>
                <script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.8.3/umd/react-dom.production.min.js"></script>
                <div id="root"></div>








                share|improve this answer

























                  0












                  0








                  0







                  You'll need a way to keep track of the previous state. useState helps you keep track of the current state only. From the docs, there is a way to access the old state, by using another hook.



                  const prevRef = useRef();
                  useEffect(() =>
                  prevRef.current = userText;
                  );


                  I've updated your example to use this. And it works out.






                  const useState, useEffect, useRef = React;

                  const App = () =>
                  const [userText, setUserText] = useState("");
                  const prevRef = useRef();
                  useEffect(() =>
                  prevRef.current = userText;
                  );

                  const handleUserKeyPress = event => (keyCode >= 65 && keyCode <= 90))
                  setUserText(`$prevRef.current$key`);

                  ;

                  useEffect(() =>
                  window.addEventListener("keydown", handleUserKeyPress);

                  return () =>
                  window.removeEventListener("keydown", handleUserKeyPress);
                  ;
                  , []);

                  return (
                  <div>
                  <h1>Feel free to type!</h1>
                  <blockquote>userText</blockquote>
                  </div>
                  );
                  ;

                  ReactDOM.render(<App />, document.getElementById("root"));

                  <script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.8.3/umd/react.production.min.js"></script>
                  <script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.8.3/umd/react-dom.production.min.js"></script>
                  <div id="root"></div>








                  share|improve this answer













                  You'll need a way to keep track of the previous state. useState helps you keep track of the current state only. From the docs, there is a way to access the old state, by using another hook.



                  const prevRef = useRef();
                  useEffect(() =>
                  prevRef.current = userText;
                  );


                  I've updated your example to use this. And it works out.






                  const useState, useEffect, useRef = React;

                  const App = () =>
                  const [userText, setUserText] = useState("");
                  const prevRef = useRef();
                  useEffect(() =>
                  prevRef.current = userText;
                  );

                  const handleUserKeyPress = event => (keyCode >= 65 && keyCode <= 90))
                  setUserText(`$prevRef.current$key`);

                  ;

                  useEffect(() =>
                  window.addEventListener("keydown", handleUserKeyPress);

                  return () =>
                  window.removeEventListener("keydown", handleUserKeyPress);
                  ;
                  , []);

                  return (
                  <div>
                  <h1>Feel free to type!</h1>
                  <blockquote>userText</blockquote>
                  </div>
                  );
                  ;

                  ReactDOM.render(<App />, document.getElementById("root"));

                  <script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.8.3/umd/react.production.min.js"></script>
                  <script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.8.3/umd/react-dom.production.min.js"></script>
                  <div id="root"></div>








                  const useState, useEffect, useRef = React;

                  const App = () =>
                  const [userText, setUserText] = useState("");
                  const prevRef = useRef();
                  useEffect(() =>
                  prevRef.current = userText;
                  );

                  const handleUserKeyPress = event => (keyCode >= 65 && keyCode <= 90))
                  setUserText(`$prevRef.current$key`);

                  ;

                  useEffect(() =>
                  window.addEventListener("keydown", handleUserKeyPress);

                  return () =>
                  window.removeEventListener("keydown", handleUserKeyPress);
                  ;
                  , []);

                  return (
                  <div>
                  <h1>Feel free to type!</h1>
                  <blockquote>userText</blockquote>
                  </div>
                  );
                  ;

                  ReactDOM.render(<App />, document.getElementById("root"));

                  <script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.8.3/umd/react.production.min.js"></script>
                  <script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.8.3/umd/react-dom.production.min.js"></script>
                  <div id="root"></div>





                  const useState, useEffect, useRef = React;

                  const App = () =>
                  const [userText, setUserText] = useState("");
                  const prevRef = useRef();
                  useEffect(() =>
                  prevRef.current = userText;
                  );

                  const handleUserKeyPress = event => (keyCode >= 65 && keyCode <= 90))
                  setUserText(`$prevRef.current$key`);

                  ;

                  useEffect(() =>
                  window.addEventListener("keydown", handleUserKeyPress);

                  return () =>
                  window.removeEventListener("keydown", handleUserKeyPress);
                  ;
                  , []);

                  return (
                  <div>
                  <h1>Feel free to type!</h1>
                  <blockquote>userText</blockquote>
                  </div>
                  );
                  ;

                  ReactDOM.render(<App />, document.getElementById("root"));

                  <script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.8.3/umd/react.production.min.js"></script>
                  <script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.8.3/umd/react-dom.production.min.js"></script>
                  <div id="root"></div>






                  share|improve this answer












                  share|improve this answer



                  share|improve this answer










                  answered Apr 8 at 3:03









                  Maaz Syed AdeebMaaz Syed Adeeb

                  2,70721526




                  2,70721526





















                      -1














                      In the second approach, the useEffect is bound only once and hence the userText never gets updated. One approach would be to maintain a local variable which gets updated along with the userText object on every keypress.



                       const [userText, setUserText] = useState('');
                      let local_text = userText
                      const handleUserKeyPress = event => ;

                      useEffect(() =>
                      window.addEventListener('keydown', handleUserKeyPress);

                      return () =>
                      window.removeEventListener('keydown', handleUserKeyPress);
                      ;
                      , []);

                      return (
                      <div>
                      <h1>Feel free to type!</h1>
                      <blockquote>userText</blockquote>
                      </div>
                      );


                      Personally I don't like the solution, feels anti-react and I think the first method is good enough and is designed to be used that way.






                      share|improve this answer

























                      • Do you mind to include some code to demonstrate how to achieve my objective in second method?

                        – Isaac
                        Apr 8 at 2:51















                      -1














                      In the second approach, the useEffect is bound only once and hence the userText never gets updated. One approach would be to maintain a local variable which gets updated along with the userText object on every keypress.



                       const [userText, setUserText] = useState('');
                      let local_text = userText
                      const handleUserKeyPress = event => ;

                      useEffect(() =>
                      window.addEventListener('keydown', handleUserKeyPress);

                      return () =>
                      window.removeEventListener('keydown', handleUserKeyPress);
                      ;
                      , []);

                      return (
                      <div>
                      <h1>Feel free to type!</h1>
                      <blockquote>userText</blockquote>
                      </div>
                      );


                      Personally I don't like the solution, feels anti-react and I think the first method is good enough and is designed to be used that way.






                      share|improve this answer

























                      • Do you mind to include some code to demonstrate how to achieve my objective in second method?

                        – Isaac
                        Apr 8 at 2:51













                      -1












                      -1








                      -1







                      In the second approach, the useEffect is bound only once and hence the userText never gets updated. One approach would be to maintain a local variable which gets updated along with the userText object on every keypress.



                       const [userText, setUserText] = useState('');
                      let local_text = userText
                      const handleUserKeyPress = event => ;

                      useEffect(() =>
                      window.addEventListener('keydown', handleUserKeyPress);

                      return () =>
                      window.removeEventListener('keydown', handleUserKeyPress);
                      ;
                      , []);

                      return (
                      <div>
                      <h1>Feel free to type!</h1>
                      <blockquote>userText</blockquote>
                      </div>
                      );


                      Personally I don't like the solution, feels anti-react and I think the first method is good enough and is designed to be used that way.






                      share|improve this answer















                      In the second approach, the useEffect is bound only once and hence the userText never gets updated. One approach would be to maintain a local variable which gets updated along with the userText object on every keypress.



                       const [userText, setUserText] = useState('');
                      let local_text = userText
                      const handleUserKeyPress = event => ;

                      useEffect(() =>
                      window.addEventListener('keydown', handleUserKeyPress);

                      return () =>
                      window.removeEventListener('keydown', handleUserKeyPress);
                      ;
                      , []);

                      return (
                      <div>
                      <h1>Feel free to type!</h1>
                      <blockquote>userText</blockquote>
                      </div>
                      );


                      Personally I don't like the solution, feels anti-react and I think the first method is good enough and is designed to be used that way.







                      share|improve this answer














                      share|improve this answer



                      share|improve this answer








                      edited Apr 8 at 3:04

























                      answered Apr 8 at 2:49









                      varun agarwalvarun agarwal

                      98529




                      98529












                      • Do you mind to include some code to demonstrate how to achieve my objective in second method?

                        – Isaac
                        Apr 8 at 2:51

















                      • Do you mind to include some code to demonstrate how to achieve my objective in second method?

                        – Isaac
                        Apr 8 at 2:51
















                      Do you mind to include some code to demonstrate how to achieve my objective in second method?

                      – Isaac
                      Apr 8 at 2:51





                      Do you mind to include some code to demonstrate how to achieve my objective in second method?

                      – Isaac
                      Apr 8 at 2:51











                      -1














                      you dont have access to the changed useText state. you can comapre it to the prevState. store the state in a variable e.g.: state like so:



                      const App = () => 
                      const [userText, setUserText] = useState('');

                      useEffect(() =>
                      let state = ''

                      const handleUserKeyPress = event => ;
                      window.addEventListener('keydown', handleUserKeyPress);
                      return () =>
                      window.removeEventListener('keydown', handleUserKeyPress);
                      ;
                      , []);

                      return (
                      <div>
                      <h1>Feel free to type!</h1>
                      <blockquote>userText</blockquote>
                      </div>
                      );
                      ;





                      share|improve this answer





























                        -1














                        you dont have access to the changed useText state. you can comapre it to the prevState. store the state in a variable e.g.: state like so:



                        const App = () => 
                        const [userText, setUserText] = useState('');

                        useEffect(() =>
                        let state = ''

                        const handleUserKeyPress = event => ;
                        window.addEventListener('keydown', handleUserKeyPress);
                        return () =>
                        window.removeEventListener('keydown', handleUserKeyPress);
                        ;
                        , []);

                        return (
                        <div>
                        <h1>Feel free to type!</h1>
                        <blockquote>userText</blockquote>
                        </div>
                        );
                        ;





                        share|improve this answer



























                          -1












                          -1








                          -1







                          you dont have access to the changed useText state. you can comapre it to the prevState. store the state in a variable e.g.: state like so:



                          const App = () => 
                          const [userText, setUserText] = useState('');

                          useEffect(() =>
                          let state = ''

                          const handleUserKeyPress = event => ;
                          window.addEventListener('keydown', handleUserKeyPress);
                          return () =>
                          window.removeEventListener('keydown', handleUserKeyPress);
                          ;
                          , []);

                          return (
                          <div>
                          <h1>Feel free to type!</h1>
                          <blockquote>userText</blockquote>
                          </div>
                          );
                          ;





                          share|improve this answer















                          you dont have access to the changed useText state. you can comapre it to the prevState. store the state in a variable e.g.: state like so:



                          const App = () => 
                          const [userText, setUserText] = useState('');

                          useEffect(() =>
                          let state = ''

                          const handleUserKeyPress = event => ;
                          window.addEventListener('keydown', handleUserKeyPress);
                          return () =>
                          window.removeEventListener('keydown', handleUserKeyPress);
                          ;
                          , []);

                          return (
                          <div>
                          <h1>Feel free to type!</h1>
                          <blockquote>userText</blockquote>
                          </div>
                          );
                          ;






                          share|improve this answer














                          share|improve this answer



                          share|improve this answer








                          edited Apr 8 at 17:14

























                          answered Apr 8 at 3:34









                          di3di3

                          491210




                          491210



























                              draft saved

                              draft discarded
















































                              Thanks for contributing an answer to Stack Overflow!


                              • Please be sure to answer the question. Provide details and share your research!

                              But avoid


                              • Asking for help, clarification, or responding to other answers.

                              • Making statements based on opinion; back them up with references or personal experience.

                              To learn more, see our tips on writing great answers.




                              draft saved


                              draft discarded














                              StackExchange.ready(
                              function ()
                              StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f55565444%2fhow-to-register-event-with-useeffect-hooks%23new-answer', 'question_page');

                              );

                              Post as a guest















                              Required, but never shown





















































                              Required, but never shown














                              Required, but never shown












                              Required, but never shown







                              Required, but never shown

































                              Required, but never shown














                              Required, but never shown












                              Required, but never shown







                              Required, but never shown







                              Popular posts from this blog

                              Hidroelektrana Sadržaj Povijest | Podjela hidroelektrana | Snaga dobivena u hidroelektranama | Dijelovi hidroelektrane | Uloga hidroelektrana u suvremenom svijetu | Prednosti hidroelektrana | Nedostaci hidroelektrana | Države s najvećom proizvodnjom hidro-električne energije | Deset najvećih hidroelektrana u svijetu | Hidroelektrane u Hrvatskoj | Izvori | Poveznice | Vanjske poveznice | Navigacijski izbornikTechnical Report, Version 2Zajedničkom poslužiteljuHidroelektranaHEP Proizvodnja d.o.o. - Hidroelektrane u Hrvatskoj

                              WordPress Information needed

                              Oconto (Nebraska) Índice Demografia | Geografia | Localidades na vizinhança | Referências Ligações externas | Menu de navegação41° 8' 29" N 99° 45' 41" O41° 8' 29" N 99° 45' 41" OU.S. Census Bureau. Census 2000 Summary File 1U.S. Census Bureau. Estimativa da população (julho de 2006)U.S. Board on Geographic Names. Topical Gazetteers Populated Places. Gráficos do banco de dados de altitudes dos Estados Unidos da AméricaEstatísticas, mapas e outras informações sobre Oconto em city-data.com