I had the same problem, but then I realized we need to check where we want to reference using the useRef. When you create a dropdown like that, you need to reference the whole div that contains the Button and the Dropdown menu. My mistake was, I put the ref prop only in the dropdown menu, and above was my button to toggle the dropdown, when I move my ref to the whole div that contains both button and dropdown, it solved the problem, because on the useEffect we want to setClose if the ref contains the div. It will return undefined because if you hide the dropdown menu and reference it using useRef, when the react mounts, the reference will be undefined, because it is hidden. Putting the ref ={} on the div that holds both button and dropdown menu solved the problem.
Not only I got perfect solution for my problem But also I learned a new cool technique (creating hook) to handle this problem with more efficiency ! Thank you very much !!!!
the way of doing the coding makes it better to understand the context and help to lose less time each time we go through it for a modification or anything. As if when riding a bike, if every time we need to assembly it and then ride it, it is better if it's ready and prepared just like normally would be.
FYI, i see the comments they have problems when click button to close, the state set to true back because you wrong to put ref. put ref into wrapper click button.
I noticed that after closing the menu, the mousedown event is still being called. Put a console log in the maybeHandler and you'll see the log after the menu closed.
I had an error 'Cannot read property 'contains' of unidentified and spend hours looking for the solution. Not sure what is different in my environment from Ryan and others, but the fix is very simple. where you have '!domNode.current.contains' you need to add 'domNode.current &&' so the full line will look like this: if ('domNode.current && !!domNode.current.contains(target.event)) {
What if the toggle button is outside the node where you put the ref at? I have something like this & the button’s detected as a click outside event that when I click on, it closes the component & quickly open it again. I want to have the click outside functionality along with the toggle when the button’s outside of the ref area.
I implemented something similar, where I have a header menu with a button to open a pop-up. But somehow, the pop-up won't show because as soon as I click the button, it closes the pop-up in the mean time because I think I am technically clicking outside the pop-up. Hmmm. Someone help>?
I have it working with one menu component on the page that uses the hook, but when I have multiple menu components on the page, only one of them works properly, the other ones close outside and when you click the menu. If that can be resolved, how can Imake this a global hook, so I don't have to have it it my menu and select components?
i have done this but if i giving the same ref in the another div in the same component. The another div working perfectly but the first div have an issue that when i click the button it opens but if i click the button again it toggles to close and opens automatically. Do i have to use two different refs or something?
Great explanation, ty. Question tho: what if I'm trying to do this from a component, and the state that I want to modify isn't in the component? The state is in a level above in my index.js file. I've passed the prop 'toggleState' which calls my 'toggleState()' function held in my index.js, but she ain't taking. Thanks for your help
I might be wrong, but I don't think that clean-up function never gets called. My understanding is that the useEffect return func only gets called when the component it is in unmounts.
Appreciate your help? I'm eager to know, how did you come across this solution? Please... I'm asking because I want to know why I'm not able to figure out this myself on my own. What should I be really looking for and what am I really lacking that is keeping me behind.
Hi Nishant! React hooks are really hard to write and they don't come naturally, especially when you first start using functional components. The best way to find these solutions is to write A LOT of React. For practice try to write a few hooks on your own and then use Google and see what other people did to solve the problem.
Hi Alok! The reason we have to clean up the effect and remove the event listener is because otherwise the listener would stay attached to the document forever. Ever time we rendered a component the document would end up getting another new listener. Eventually there would be so many listeners that it would cause a memory leak. Using the cleanup function allows us to tear down the listener and prevent any sort of memory leak from ever happening.
Can we make this as helper function so that we can use the same functionality in other components as well. Question: in helper function case should I pass the ref as the second argument to that function?
Please help. Everything works but if i click my menu button again the hook triggers and it closes the menu BUT the button triggers and it opens again. So im stack with an open menu that closes only if i click outside the menu AND outside the menu button. What should i do?
@@siddhant3852 i dont remember exactly what i did but i think i removed the button listener when the menu was open. Then if i clicked the button it would just fire the hook to close the menu and when the menu was closed i would add te listener again.
In my application, I'm navigating between routes. The event handler works fine when I'm on the concerned page, but since component mounts/unmounts with route changes, "ref.current" was going back to "null" when routing back to the page, thus throwing error: "Cannot read property 'contains' of null" . 😅Easy fix: clean-up handler function with "removeEventListener".
Hey can someone help me, I did my code precisely the same as this tutorial but in my case, the click-outside-to-close didn't work. I assume it is because the "contains" property doesn't exist? I don't even know what it means please help!
useEffect(() => { document.addEventListener("mousedown", (e) => { if(domNode.current && !domNode.current.contains(e.target)){ setShowDropdownOne(false); } }); }); and I did referenced 'domNode' in my dropdown tag, please somebody enlighten me if my code is wrong
Hey Ryan, You're awesome teacher. I love your teaching style. Can you tell me please what software you are using to draw rectangle area by mouse cursor which indicate the height and width? :)
Cannot read property 'contains' can be fixed by changing current.contains to current?.contains
I had the same problem, but then I realized we need to check where we want to reference using the useRef.
When you create a dropdown like that, you need to reference the whole div that contains the Button and the Dropdown menu.
My mistake was, I put the ref prop only in the dropdown menu, and above was my button to toggle the dropdown, when I move my ref to the whole div that contains both button and dropdown, it solved the problem, because on the useEffect we want to setClose if the ref contains the div.
It will return undefined because if you hide the dropdown menu and reference it using useRef, when the react mounts, the reference will be undefined, because it is hidden.
Putting the ref ={} on the div that holds both button and dropdown menu solved the problem.
You're amazing... Thanks
@@luishenriqueandradepellizz680 thank you for your comment!! big help!!
What a great simple-to-understand solution. I was searching for this all over the web and could not find this kind of solution.
Thanks a lot, man.
This was exactly what I was looking for! Thanks, Ryan!
Not only I got perfect solution for my problem
But also I learned a new cool technique (creating hook) to handle this problem with more efficiency !
Thank you very much !!!!
Thanks, very clear! Thanks for taking that one extra step at the end about designing a reusable hook :)
Clear and straightforward explanation, just what I'm looking for thanks.
your way of doing it was much easier, faster and clearer then others i saw online. thank you!!
Thanks Mate . Great explanation and it was short and to the point
What a clear explanation, thank you so much, Ryan! My problem is now solved and you have a faithful new subscriber.
Thank you for this. I used this code in my project and referenced this video in the code. Please make more practical videos like this!
It is in fact very nice Ryan, your explanation also, clear and concise. Thanks a lot! Greetings from Argentina.
Many many thanks Sir...🙂🙂
I've solved a problem watching your video🙂
Simple and precise.....you just saved the day champ
You beauty... What a clear explanation. Hats off sir. I immediately subscribed to your channel. You are a great teacher. Thanks a lot 👍👍
You saved my life. I've been searching for this for months, thanks a lot.
This is a simple but powerful solution really handy
Thank you so so much. I was looking for this for a long time. May God bless you.
Thanks for this vid ryan! amazingly well explained! I gave helped solve that feature I didn't know how to implement with hooks
That was exactly what I was looking for! Thank you, Ryan!
the way of doing the coding makes it better to understand the context and help to lose less time each time we go through it for a modification or anything.
As if when riding a bike, if every time we need to assembly it and then ride it, it is better if it's ready and prepared just like normally would be.
Thanks for you from Brazil!!! You helped me a lot
Thank you very much for the excellent explanation, Ryan! Your code worked like a charm!
Excellent explanation, super helpful - I built some cool modals with this. Thank you Ryan :)
FYI, i see the comments they have problems when click button to close, the state set to true back because you wrong to put ref. put ref into wrapper click button.
well then we have the same problem we started with , the menu will close when we click any menu button
Thank you!
God Damn!! This was brilliant, no one else online has a solution like this!⭐⭐⭐⭐⭐
Even though I was searching for Vue solution but yours is expressive. Maybe I'll write something like this using Vue
Great explanation ryan keep up the good work!
Well done Ryan, this was very helpful for me.
Great job Ryan! Superbe explanation!
Excellent trick thank you so much 👌🏼👌🏼👌🏼
I noticed that after closing the menu, the mousedown event is still being called. Put a console log in the maybeHandler and you'll see the log after the menu closed.
amazing work... straight to point, thank you so much!
Exactly what I needed to learn, thanks
Thank you for the video! Saved me so much time.
Thank you so much Ryan, its really helpful
thank you for the video, the explanations were very clear and it helped me a lot !
I needed this🎉
thank you bro i don't speak english very well but thank you for to share your knowledge
You teach so well! Thanks!
I had an error 'Cannot read property 'contains' of unidentified and spend hours looking for the solution. Not sure what is different in my environment from Ryan and others, but the fix is very simple. where you have '!domNode.current.contains' you need to add 'domNode.current &&' so the full line will look like this:
if ('domNode.current && !!domNode.current.contains(target.event)) {
Thanks for fixing that Alexey! I'm sure this will help others that run into the same problem.
thank you so much
I had the same error. It did the trick, thanks!
I had same problem but I follow what you say but still having issues, do you have a example code working?
I'm going through that right now kkk. Hope you're comment works
Thank you! Great video
Thanks so much for the video man, it really help me a lot, I'm so gratefull :)
thank you so much this video was so helpful
Great video! Very well explained
it is working, just amazing, thank you bro
Да где ты раньше был? СПАСИБО!
What if the toggle button is outside the node where you put the ref at? I have something like this & the button’s detected as a click outside event that when I click on, it closes the component & quickly open it again. I want to have the click outside functionality along with the toggle when the button’s outside of the ref area.
I implemented something similar, where I have a header menu with a button to open a pop-up. But somehow, the pop-up won't show because as soon as I click the button, it closes the pop-up in the mean time because I think I am technically clicking outside the pop-up. Hmmm. Someone help>?
Thankyou so much , it really helped.
I have it working with one menu component on the page that uses the hook, but when I have multiple menu components on the page, only one of them works properly, the other ones close outside and when you click the menu. If that can be resolved, how can Imake this a global hook, so I don't have to have it it my menu and select components?
you are a life saver
Great explanation!
You save my day Thanks :)
What if you had multiple menus on the same page? The document click listeners will be attached multiple times
awesome, but how it supposed to work if the button component is outside the ref component?
very nice video it saved my precious time. Thankyou.
i have done this but if i giving the same ref in the another div in the same component. The another div working perfectly but the first div have an issue that when i click the button it opens but if i click the button again it toggles to close and opens automatically. Do i have to use two different refs or something?
So perfect. Thank you so much 🙏🙏
Thank you bro 🎉
Great explanation, ty. Question tho: what if I'm trying to do this from a component, and the state that I want to modify isn't in the component? The state is in a level above in my index.js file. I've passed the prop 'toggleState' which calls my 'toggleState()' function held in my index.js, but she ain't taking.
Thanks for your help
I might be wrong, but I don't think that clean-up function never gets called. My understanding is that the useEffect return func only gets called when the component it is in unmounts.
can it work for 2 elements? example dropdown when opened first then i click to second.
Nice explanation :-)
Thank you very much. this video help me very mouch
This is gold
Thank you for the video.
Amazing, I like this approach. Thanks!
Nice man, thank you
Appreciate your help? I'm eager to know, how did you come across this solution? Please... I'm asking because I want to know why I'm not able to figure out this myself on my own. What should I be really looking for and what am I really lacking that is keeping me behind.
Hi Nishant! React hooks are really hard to write and they don't come naturally, especially when you first start using functional components. The best way to find these solutions is to write A LOT of React.
For practice try to write a few hooks on your own and then use Google and see what other people did to solve the problem.
@@RyanToronto Thanks Ryan for taking time for me. I feel so grateful. Thank you so much.
Thanks for the great tutorial. I have a question. Why do we need to remove the eventlistener?
Thats great one !!..... Can you please let me know why do we need to clean up the effect like removing event listner ??
Hi Alok! The reason we have to clean up the effect and remove the event listener is because otherwise the listener would stay attached to the document forever. Ever time we rendered a component the document would end up getting another new listener. Eventually there would be so many listeners that it would cause a memory leak.
Using the cleanup function allows us to tear down the listener and prevent any sort of memory leak from ever happening.
@@RyanToronto Thank you so much for your response. Really helpful video.
thank you very much❤❤
Legend.👌
thank you soo much, worked
Thank you so much. It helped
Thanks, I like your style... :)
Can we make this as helper function so that we can use the same functionality in other components as well.
Question: in helper function case should I pass the ref as the second argument to that function?
No need to make a helper function. You can export the hook to share it between multiple components.
Can this work with react bootstrap nav drop down toggle button? I tried it but it’s taking 2 clicks to activate the drop down for some reason.
Awesome explanation +++++++++++++++++++++++++++++ Thank You
Thank you it helped me lot
thank you ❤❤
Thanks a lot!
Vim de outro pais dizer que amei o vídeo.
Please help.
Everything works but if i click my menu button again the hook triggers and it closes the menu BUT the button triggers and it opens again.
So im stack with an open menu that closes only if i click outside the menu AND outside the menu button. What should i do?
did you find the solution?
@@siddhant3852 i dont remember exactly what i did but i think i removed the button listener when the menu was open. Then if i clicked the button it would just fire the hook to close the menu and when the menu was closed i would add te listener again.
well explained thanks.
In my application, I'm navigating between routes. The event handler works fine when I'm on the concerned page, but since component mounts/unmounts with route changes, "ref.current" was going back to "null" when routing back to the page, thus throwing error: "Cannot read property 'contains' of null" .
😅Easy fix: clean-up handler function with "removeEventListener".
Awesome fix Sanjib! I'll pin your comment because I'm sure it will help others.
@@RyanToronto Happy to help. Thanks for the easy tutorial.
thank you for this
Great it worked
awesome !!! thank you so much.
problem: when I click button to close, the state becomes true again , because of it I can't toggle open and close. any possible solution for this?
using "click" instead of "mousedown" solves the problem.
Hey can someone help me, I did my code precisely the same as this tutorial but in my case, the click-outside-to-close didn't work. I assume it is because the "contains" property doesn't exist? I don't even know what it means please help!
const [showDropdownOne ,setShowDropdownOne] = useState(false);
const domNode = useRef();
useEffect(() => {
document.addEventListener("mousedown", (e) => {
if(domNode.current && !domNode.current.contains(e.target)){
setShowDropdownOne(false);
}
});
});
and I did referenced 'domNode' in my dropdown tag, please somebody enlighten me if my code is wrong
Stupendous
Amazing!
Hey Ryan, You're awesome teacher. I love your teaching style. Can you tell me please what software you are using to draw rectangle area by mouse cursor which indicate the height and width? :)
Hi Hamidur! It's the Mac OSX screen shot tool (cmd+shift+4).
@@RyanToronto Thanks Ryan
Thank you :)
Thanks buddy
Thanks!
thank u very much
NIce
ty bro