How to register event with useEffect hooks?How do JavaScript closures work?How do I check if an element is...
Does bootstrapped regression allow for inference?
I’m planning on buying a laser printer but concerned about the life cycle of toner in the machine
How do I create uniquely male characters?
Shall I use personal or official e-mail account when registering to external websites for work purpose?
Is every set a filtered colimit of finite sets?
Doomsday-clock for my fantasy planet
What is GPS' 19 year rollover and does it present a cybersecurity issue?
Does it makes sense to buy a new cycle to learn riding?
What do you call something that goes against the spirit of the law, but is legal when interpreting the law to the letter?
Finding files for which a command fails
Patience, young "Padovan"
Calculate Levenshtein distance between two strings in Python
How to answer pointed "are you quitting" questioning when I don't want them to suspect
Does the average primeness of natural numbers tend to zero?
I see my dog run
Can I find out the caloric content of bread by dehydrating it?
Domain expired, GoDaddy holds it and is asking more money
Is Fable (1996) connected in any way to the Fable franchise from Lionhead Studios?
Is it wise to focus on putting odd beats on left when playing double bass drums?
Why do we use polarized capacitors?
A poker game description that does not feel gimmicky
What do the Banks children have against barley water?
LWC and complex parameters
Unbreakable Formation vs. Cry of the Carnarium
How to register event with useEffect hooks?
How 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?How to use foreach with 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;
}
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 => {
const { key, keyCode } = event;
if (keyCode === 32 || (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
add a comment |
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 => {
const { key, keyCode } = event;
if (keyCode === 32 || (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
add a comment |
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 => {
const { key, keyCode } = event;
if (keyCode === 32 || (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
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 => {
const { key, keyCode } = event;
if (keyCode === 32 || (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
javascript reactjs react-hooks
edited 15 hours ago
John Kennedy
3,02021228
3,02021228
asked yesterday
IsaacIsaac
3,7842830
3,7842830
add a comment |
add a comment |
6 Answers
6
active
oldest
votes
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 || (keyCode >= 65 && keyCode <= 90)) {
setUserText(prevUserText => `${prevUserText}${key}`);
}
}, []);
useEffect(() => {
window.addEventListener('keydown', handleUserKeyPress);
return () => {
window.removeEventListener('keydown', handleUserKeyPress);
};
}, [handleUserKeyPress]);
return (
<div>
<h1>Feel free to type!</h1>
<blockquote>{userText}</blockquote>
</div>
);
Your solution makes most sense to me as compared to others, thanks a lot!
– Isaac
22 hours ago
Glad to have helped (y)
– Shubham Khatri
21 hours ago
but this will create a new bound function every keypress. if your focus is perfromance a local state variable is much better
– di3
19 hours ago
@di3 If you useuseCallback
to define the function with empty dependency array, you won't have that issue as well
– Shubham Khatri
17 hours ago
yes that would work too. just wanted to point it out
– di3
17 hours ago
|
show 3 more comments
try this, it works same as your original code:
useEffect(() => {
function handlekeydownEvent(event) {
const { key, keyCode } = event;
if (keyCode === 32 || (keyCode >= 65 && keyCode <= 90)) {
setUserText(`${userText}${key}`);
}
}
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.
By adding[userText]
is exactly the same as without second argument, right? Reason is I only haveuserText
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
yesterday
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 solutionuseEffect()
depend on theuserText
variable but you didn't put inside the second arguments.
– Spark.Bao
yesterday
But by adding in[userText]
, it also means register and deregister the event on every re-render right?
– Isaac
yesterday
exactly! that why I say it is same with your first solution.
– Spark.Bao
yesterday
1
got what you mean, if you really want to register it only one time in this example, then you need to useuseRef
, just as @Maaz Syed Adeeb 's answer.
– Spark.Bao
yesterday
|
show 4 more comments
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 || (keyCode >= 65 && keyCode <= 90)) {
setUserText(prevUserText => `${prevUserText}${key}`);
}
}, []);
useEffect(() => {
window.addEventListener("keydown", handleUserKeyPress);
return () => {
window.removeEventListener("keydown", handleUserKeyPress);
};
}, [handleUserKeyPress]);
return (
<div>
<blockquote>{userText}</blockquote>
</div>
);
I've tried your solution, but it's exactly the same as[userText]
or without second argument. Basically we put aconsole.log
insideuseEffect
, we will see that the logging is firing every re-render, which also means,addEventListender
is running every re-render
– Isaac
yesterday
I want to believe that is an expected behaviour. I updated my answer.
– John Kennedy
yesterday
On your sandbox, you've put a statementconsole.log('>');
withinuseEffect
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
yesterday
1
but because ofreturn () => {window.removeEventListener('keydown', handleUserKeyPress)}
, on every re-render, the component will register and deregister
– Isaac
23 hours ago
1
Exactly the behaviour that I wished for, but you can observe it @ codesandbox.io/s/n5j7qy051j
– Isaac
23 hours ago
|
show 5 more comments
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 => {
const { key, keyCode } = event;
if (keyCode === 32 || (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>
add a comment |
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 => {
const { key, keyCode } = event;
if (keyCode === 32 || (keyCode >= 65 && keyCode <= 90)) {
local_text = `${userText}${key}`;
setUserText(local_text);
}
};
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.
Do you mind to include some code to demonstrate how to achieve my objective in second method?
– Isaac
yesterday
add a comment |
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 => {
const { key, keyCode } = event;
if (keyCode === 32 || (keyCode >= 65 && keyCode <= 90)) {
state += `${key}`
setUserText(state);
}
};
window.addEventListener('keydown', handleUserKeyPress);
return () => {
window.removeEventListener('keydown', handleUserKeyPress);
};
}, []);
return (
<div>
<h1>Feel free to type!</h1>
<blockquote>{userText}</blockquote>
</div>
);
};
add a comment |
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
});
}
});
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
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
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 || (keyCode >= 65 && keyCode <= 90)) {
setUserText(prevUserText => `${prevUserText}${key}`);
}
}, []);
useEffect(() => {
window.addEventListener('keydown', handleUserKeyPress);
return () => {
window.removeEventListener('keydown', handleUserKeyPress);
};
}, [handleUserKeyPress]);
return (
<div>
<h1>Feel free to type!</h1>
<blockquote>{userText}</blockquote>
</div>
);
Your solution makes most sense to me as compared to others, thanks a lot!
– Isaac
22 hours ago
Glad to have helped (y)
– Shubham Khatri
21 hours ago
but this will create a new bound function every keypress. if your focus is perfromance a local state variable is much better
– di3
19 hours ago
@di3 If you useuseCallback
to define the function with empty dependency array, you won't have that issue as well
– Shubham Khatri
17 hours ago
yes that would work too. just wanted to point it out
– di3
17 hours ago
|
show 3 more comments
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 || (keyCode >= 65 && keyCode <= 90)) {
setUserText(prevUserText => `${prevUserText}${key}`);
}
}, []);
useEffect(() => {
window.addEventListener('keydown', handleUserKeyPress);
return () => {
window.removeEventListener('keydown', handleUserKeyPress);
};
}, [handleUserKeyPress]);
return (
<div>
<h1>Feel free to type!</h1>
<blockquote>{userText}</blockquote>
</div>
);
Your solution makes most sense to me as compared to others, thanks a lot!
– Isaac
22 hours ago
Glad to have helped (y)
– Shubham Khatri
21 hours ago
but this will create a new bound function every keypress. if your focus is perfromance a local state variable is much better
– di3
19 hours ago
@di3 If you useuseCallback
to define the function with empty dependency array, you won't have that issue as well
– Shubham Khatri
17 hours ago
yes that would work too. just wanted to point it out
– di3
17 hours ago
|
show 3 more comments
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 || (keyCode >= 65 && keyCode <= 90)) {
setUserText(prevUserText => `${prevUserText}${key}`);
}
}, []);
useEffect(() => {
window.addEventListener('keydown', handleUserKeyPress);
return () => {
window.removeEventListener('keydown', handleUserKeyPress);
};
}, [handleUserKeyPress]);
return (
<div>
<h1>Feel free to type!</h1>
<blockquote>{userText}</blockquote>
</div>
);
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 || (keyCode >= 65 && keyCode <= 90)) {
setUserText(prevUserText => `${prevUserText}${key}`);
}
}, []);
useEffect(() => {
window.addEventListener('keydown', handleUserKeyPress);
return () => {
window.removeEventListener('keydown', handleUserKeyPress);
};
}, [handleUserKeyPress]);
return (
<div>
<h1>Feel free to type!</h1>
<blockquote>{userText}</blockquote>
</div>
);
edited 10 hours ago
answered 22 hours ago
Shubham KhatriShubham Khatri
95.9k15121161
95.9k15121161
Your solution makes most sense to me as compared to others, thanks a lot!
– Isaac
22 hours ago
Glad to have helped (y)
– Shubham Khatri
21 hours ago
but this will create a new bound function every keypress. if your focus is perfromance a local state variable is much better
– di3
19 hours ago
@di3 If you useuseCallback
to define the function with empty dependency array, you won't have that issue as well
– Shubham Khatri
17 hours ago
yes that would work too. just wanted to point it out
– di3
17 hours ago
|
show 3 more comments
Your solution makes most sense to me as compared to others, thanks a lot!
– Isaac
22 hours ago
Glad to have helped (y)
– Shubham Khatri
21 hours ago
but this will create a new bound function every keypress. if your focus is perfromance a local state variable is much better
– di3
19 hours ago
@di3 If you useuseCallback
to define the function with empty dependency array, you won't have that issue as well
– Shubham Khatri
17 hours ago
yes that would work too. just wanted to point it out
– di3
17 hours ago
Your solution makes most sense to me as compared to others, thanks a lot!
– Isaac
22 hours ago
Your solution makes most sense to me as compared to others, thanks a lot!
– Isaac
22 hours ago
Glad to have helped (y)
– Shubham Khatri
21 hours ago
Glad to have helped (y)
– Shubham Khatri
21 hours ago
but this will create a new bound function every keypress. if your focus is perfromance a local state variable is much better
– di3
19 hours ago
but this will create a new bound function every keypress. if your focus is perfromance a local state variable is much better
– di3
19 hours ago
@di3 If you use
useCallback
to define the function with empty dependency array, you won't have that issue as well– Shubham Khatri
17 hours ago
@di3 If you use
useCallback
to define the function with empty dependency array, you won't have that issue as well– Shubham Khatri
17 hours ago
yes that would work too. just wanted to point it out
– di3
17 hours ago
yes that would work too. just wanted to point it out
– di3
17 hours ago
|
show 3 more comments
try this, it works same as your original code:
useEffect(() => {
function handlekeydownEvent(event) {
const { key, keyCode } = event;
if (keyCode === 32 || (keyCode >= 65 && keyCode <= 90)) {
setUserText(`${userText}${key}`);
}
}
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.
By adding[userText]
is exactly the same as without second argument, right? Reason is I only haveuserText
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
yesterday
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 solutionuseEffect()
depend on theuserText
variable but you didn't put inside the second arguments.
– Spark.Bao
yesterday
But by adding in[userText]
, it also means register and deregister the event on every re-render right?
– Isaac
yesterday
exactly! that why I say it is same with your first solution.
– Spark.Bao
yesterday
1
got what you mean, if you really want to register it only one time in this example, then you need to useuseRef
, just as @Maaz Syed Adeeb 's answer.
– Spark.Bao
yesterday
|
show 4 more comments
try this, it works same as your original code:
useEffect(() => {
function handlekeydownEvent(event) {
const { key, keyCode } = event;
if (keyCode === 32 || (keyCode >= 65 && keyCode <= 90)) {
setUserText(`${userText}${key}`);
}
}
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.
By adding[userText]
is exactly the same as without second argument, right? Reason is I only haveuserText
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
yesterday
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 solutionuseEffect()
depend on theuserText
variable but you didn't put inside the second arguments.
– Spark.Bao
yesterday
But by adding in[userText]
, it also means register and deregister the event on every re-render right?
– Isaac
yesterday
exactly! that why I say it is same with your first solution.
– Spark.Bao
yesterday
1
got what you mean, if you really want to register it only one time in this example, then you need to useuseRef
, just as @Maaz Syed Adeeb 's answer.
– Spark.Bao
yesterday
|
show 4 more comments
try this, it works same as your original code:
useEffect(() => {
function handlekeydownEvent(event) {
const { key, keyCode } = event;
if (keyCode === 32 || (keyCode >= 65 && keyCode <= 90)) {
setUserText(`${userText}${key}`);
}
}
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.
try this, it works same as your original code:
useEffect(() => {
function handlekeydownEvent(event) {
const { key, keyCode } = event;
if (keyCode === 32 || (keyCode >= 65 && keyCode <= 90)) {
setUserText(`${userText}${key}`);
}
}
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.
edited yesterday
answered yesterday
Spark.BaoSpark.Bao
2,6511730
2,6511730
By adding[userText]
is exactly the same as without second argument, right? Reason is I only haveuserText
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
yesterday
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 solutionuseEffect()
depend on theuserText
variable but you didn't put inside the second arguments.
– Spark.Bao
yesterday
But by adding in[userText]
, it also means register and deregister the event on every re-render right?
– Isaac
yesterday
exactly! that why I say it is same with your first solution.
– Spark.Bao
yesterday
1
got what you mean, if you really want to register it only one time in this example, then you need to useuseRef
, just as @Maaz Syed Adeeb 's answer.
– Spark.Bao
yesterday
|
show 4 more comments
By adding[userText]
is exactly the same as without second argument, right? Reason is I only haveuserText
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
yesterday
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 solutionuseEffect()
depend on theuserText
variable but you didn't put inside the second arguments.
– Spark.Bao
yesterday
But by adding in[userText]
, it also means register and deregister the event on every re-render right?
– Isaac
yesterday
exactly! that why I say it is same with your first solution.
– Spark.Bao
yesterday
1
got what you mean, if you really want to register it only one time in this example, then you need to useuseRef
, just as @Maaz Syed Adeeb 's answer.
– Spark.Bao
yesterday
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
yesterday
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
yesterday
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
yesterday
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
yesterday
But by adding in
[userText]
, it also means register and deregister the event on every re-render right?– Isaac
yesterday
But by adding in
[userText]
, it also means register and deregister the event on every re-render right?– Isaac
yesterday
exactly! that why I say it is same with your first solution.
– Spark.Bao
yesterday
exactly! that why I say it is same with your first solution.
– Spark.Bao
yesterday
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
yesterday
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
yesterday
|
show 4 more comments
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 || (keyCode >= 65 && keyCode <= 90)) {
setUserText(prevUserText => `${prevUserText}${key}`);
}
}, []);
useEffect(() => {
window.addEventListener("keydown", handleUserKeyPress);
return () => {
window.removeEventListener("keydown", handleUserKeyPress);
};
}, [handleUserKeyPress]);
return (
<div>
<blockquote>{userText}</blockquote>
</div>
);
I've tried your solution, but it's exactly the same as[userText]
or without second argument. Basically we put aconsole.log
insideuseEffect
, we will see that the logging is firing every re-render, which also means,addEventListender
is running every re-render
– Isaac
yesterday
I want to believe that is an expected behaviour. I updated my answer.
– John Kennedy
yesterday
On your sandbox, you've put a statementconsole.log('>');
withinuseEffect
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
yesterday
1
but because ofreturn () => {window.removeEventListener('keydown', handleUserKeyPress)}
, on every re-render, the component will register and deregister
– Isaac
23 hours ago
1
Exactly the behaviour that I wished for, but you can observe it @ codesandbox.io/s/n5j7qy051j
– Isaac
23 hours ago
|
show 5 more comments
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 || (keyCode >= 65 && keyCode <= 90)) {
setUserText(prevUserText => `${prevUserText}${key}`);
}
}, []);
useEffect(() => {
window.addEventListener("keydown", handleUserKeyPress);
return () => {
window.removeEventListener("keydown", handleUserKeyPress);
};
}, [handleUserKeyPress]);
return (
<div>
<blockquote>{userText}</blockquote>
</div>
);
I've tried your solution, but it's exactly the same as[userText]
or without second argument. Basically we put aconsole.log
insideuseEffect
, we will see that the logging is firing every re-render, which also means,addEventListender
is running every re-render
– Isaac
yesterday
I want to believe that is an expected behaviour. I updated my answer.
– John Kennedy
yesterday
On your sandbox, you've put a statementconsole.log('>');
withinuseEffect
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
yesterday
1
but because ofreturn () => {window.removeEventListener('keydown', handleUserKeyPress)}
, on every re-render, the component will register and deregister
– Isaac
23 hours ago
1
Exactly the behaviour that I wished for, but you can observe it @ codesandbox.io/s/n5j7qy051j
– Isaac
23 hours ago
|
show 5 more comments
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 || (keyCode >= 65 && keyCode <= 90)) {
setUserText(prevUserText => `${prevUserText}${key}`);
}
}, []);
useEffect(() => {
window.addEventListener("keydown", handleUserKeyPress);
return () => {
window.removeEventListener("keydown", handleUserKeyPress);
};
}, [handleUserKeyPress]);
return (
<div>
<blockquote>{userText}</blockquote>
</div>
);
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 || (keyCode >= 65 && keyCode <= 90)) {
setUserText(prevUserText => `${prevUserText}${key}`);
}
}, []);
useEffect(() => {
window.addEventListener("keydown", handleUserKeyPress);
return () => {
window.removeEventListener("keydown", handleUserKeyPress);
};
}, [handleUserKeyPress]);
return (
<div>
<blockquote>{userText}</blockquote>
</div>
);
edited 15 hours ago
answered yesterday
John KennedyJohn Kennedy
3,02021228
3,02021228
I've tried your solution, but it's exactly the same as[userText]
or without second argument. Basically we put aconsole.log
insideuseEffect
, we will see that the logging is firing every re-render, which also means,addEventListender
is running every re-render
– Isaac
yesterday
I want to believe that is an expected behaviour. I updated my answer.
– John Kennedy
yesterday
On your sandbox, you've put a statementconsole.log('>');
withinuseEffect
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
yesterday
1
but because ofreturn () => {window.removeEventListener('keydown', handleUserKeyPress)}
, on every re-render, the component will register and deregister
– Isaac
23 hours ago
1
Exactly the behaviour that I wished for, but you can observe it @ codesandbox.io/s/n5j7qy051j
– Isaac
23 hours ago
|
show 5 more comments
I've tried your solution, but it's exactly the same as[userText]
or without second argument. Basically we put aconsole.log
insideuseEffect
, we will see that the logging is firing every re-render, which also means,addEventListender
is running every re-render
– Isaac
yesterday
I want to believe that is an expected behaviour. I updated my answer.
– John Kennedy
yesterday
On your sandbox, you've put a statementconsole.log('>');
withinuseEffect
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
yesterday
1
but because ofreturn () => {window.removeEventListener('keydown', handleUserKeyPress)}
, on every re-render, the component will register and deregister
– Isaac
23 hours ago
1
Exactly the behaviour that I wished for, but you can observe it @ codesandbox.io/s/n5j7qy051j
– Isaac
23 hours ago
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
yesterday
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
yesterday
I want to believe that is an expected behaviour. I updated my answer.
– John Kennedy
yesterday
I want to believe that is an expected behaviour. I updated my answer.
– John Kennedy
yesterday
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
yesterday
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
yesterday
1
1
but because of
return () => {window.removeEventListener('keydown', handleUserKeyPress)}
, on every re-render, the component will register and deregister– Isaac
23 hours ago
but because of
return () => {window.removeEventListener('keydown', handleUserKeyPress)}
, on every re-render, the component will register and deregister– Isaac
23 hours ago
1
1
Exactly the behaviour that I wished for, but you can observe it @ codesandbox.io/s/n5j7qy051j
– Isaac
23 hours ago
Exactly the behaviour that I wished for, but you can observe it @ codesandbox.io/s/n5j7qy051j
– Isaac
23 hours ago
|
show 5 more comments
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 => {
const { key, keyCode } = event;
if (keyCode === 32 || (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>
add a comment |
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 => {
const { key, keyCode } = event;
if (keyCode === 32 || (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>
add a comment |
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 => {
const { key, keyCode } = event;
if (keyCode === 32 || (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>
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 => {
const { key, keyCode } = event;
if (keyCode === 32 || (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 => {
const { key, keyCode } = event;
if (keyCode === 32 || (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 => {
const { key, keyCode } = event;
if (keyCode === 32 || (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>
answered yesterday
Maaz Syed AdeebMaaz Syed Adeeb
2,66721526
2,66721526
add a comment |
add a comment |
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 => {
const { key, keyCode } = event;
if (keyCode === 32 || (keyCode >= 65 && keyCode <= 90)) {
local_text = `${userText}${key}`;
setUserText(local_text);
}
};
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.
Do you mind to include some code to demonstrate how to achieve my objective in second method?
– Isaac
yesterday
add a comment |
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 => {
const { key, keyCode } = event;
if (keyCode === 32 || (keyCode >= 65 && keyCode <= 90)) {
local_text = `${userText}${key}`;
setUserText(local_text);
}
};
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.
Do you mind to include some code to demonstrate how to achieve my objective in second method?
– Isaac
yesterday
add a comment |
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 => {
const { key, keyCode } = event;
if (keyCode === 32 || (keyCode >= 65 && keyCode <= 90)) {
local_text = `${userText}${key}`;
setUserText(local_text);
}
};
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.
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 => {
const { key, keyCode } = event;
if (keyCode === 32 || (keyCode >= 65 && keyCode <= 90)) {
local_text = `${userText}${key}`;
setUserText(local_text);
}
};
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.
edited yesterday
answered yesterday
varun agarwalvarun agarwal
98129
98129
Do you mind to include some code to demonstrate how to achieve my objective in second method?
– Isaac
yesterday
add a comment |
Do you mind to include some code to demonstrate how to achieve my objective in second method?
– Isaac
yesterday
Do you mind to include some code to demonstrate how to achieve my objective in second method?
– Isaac
yesterday
Do you mind to include some code to demonstrate how to achieve my objective in second method?
– Isaac
yesterday
add a comment |
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 => {
const { key, keyCode } = event;
if (keyCode === 32 || (keyCode >= 65 && keyCode <= 90)) {
state += `${key}`
setUserText(state);
}
};
window.addEventListener('keydown', handleUserKeyPress);
return () => {
window.removeEventListener('keydown', handleUserKeyPress);
};
}, []);
return (
<div>
<h1>Feel free to type!</h1>
<blockquote>{userText}</blockquote>
</div>
);
};
add a comment |
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 => {
const { key, keyCode } = event;
if (keyCode === 32 || (keyCode >= 65 && keyCode <= 90)) {
state += `${key}`
setUserText(state);
}
};
window.addEventListener('keydown', handleUserKeyPress);
return () => {
window.removeEventListener('keydown', handleUserKeyPress);
};
}, []);
return (
<div>
<h1>Feel free to type!</h1>
<blockquote>{userText}</blockquote>
</div>
);
};
add a comment |
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 => {
const { key, keyCode } = event;
if (keyCode === 32 || (keyCode >= 65 && keyCode <= 90)) {
state += `${key}`
setUserText(state);
}
};
window.addEventListener('keydown', handleUserKeyPress);
return () => {
window.removeEventListener('keydown', handleUserKeyPress);
};
}, []);
return (
<div>
<h1>Feel free to type!</h1>
<blockquote>{userText}</blockquote>
</div>
);
};
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 => {
const { key, keyCode } = event;
if (keyCode === 32 || (keyCode >= 65 && keyCode <= 90)) {
state += `${key}`
setUserText(state);
}
};
window.addEventListener('keydown', handleUserKeyPress);
return () => {
window.removeEventListener('keydown', handleUserKeyPress);
};
}, []);
return (
<div>
<h1>Feel free to type!</h1>
<blockquote>{userText}</blockquote>
</div>
);
};
edited 10 hours ago
answered yesterday
di3di3
491210
491210
add a comment |
add a comment |
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.
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
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
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
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