In this video I'll show you how to make a hook that runs whenever the user clicks outside of a DOM node. Source: / little-neat-trick-to-c... Code: github.com/ryanto/click-outsi...
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.
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)) {
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.
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? :)
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.
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?
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.
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>?
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.
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".
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?