Top 6 React Hook Mistakes Beginners Make

  Рет қаралды 555,344

Web Dev Simplified

Web Dev Simplified

Күн бұрын

FREE React Hooks Simplified Course: courses.webdevsimplified.com/...
📚 Materials/References:
FREE React Hooks Simplified Course: courses.webdevsimplified.com/...
Reference vs Value Video: • Reference Vs Value In ...
Reference vs Value Article: blog.webdevsimplified.com/202...
🌎 Find Me Here:
My Blog: blog.webdevsimplified.com
My Courses: courses.webdevsimplified.com
Patreon: / webdevsimplified
Twitter: / devsimplified
Discord: / discord
GitHub: github.com/WebDevSimplified
CodePen: codepen.io/WebDevSimplified
⏱️ Timestamps:
00:00 - Introduction
00:39 - Using state when you don’t need it
02:57 - Not using the function version of useState
06:44 - State does not update immediately
08:25 - Unnecessary useEffects
12:40 - Referential equality mistakes
16:55 - Not aborting fetch requests
#WebDevelopment #WDS #JavaScript

Пікірлер: 481
@IceMetalPunk
@IceMetalPunk Жыл бұрын
React's own docs explicitly recommend using state-controlled inputs over refs whenever possible. It refers to the ref method as "quick and dirty" because it lets the DOM handle tracking the value instead of React, which can sometimes cause unexpected behavior when React renders its virtual DOM. So... yeah. I think for forms, especially large ones, it's better to keep track of values in a single state object with key-value pairs. That does mean it'll re-render whenever a value changes, but since React only manipulates the DOM for the one input that's changed, it's not a big deal; and it allows React to have more control over, and more understanding of, the inputs, for optimizations. The main issue with using local variables instead of useEffect for composite values is future-proofing: when you add more state to the component, those variables will be re-evaluated on every re-render even if they don't need to be. In such cases, I think useMemo is the optimal solution; in fact, it's why useMemo exists! (And I believe recomputing a memoized variable doesn't trigger a re-render the way setting state does, though I couldn't find anything definitive about that.) But you are right that in some cases, you don't need to listen for changes at all, since you can just use the new value at the same time as you're setting it on the state.
@CraigClayton-bk3ze
@CraigClayton-bk3ze Жыл бұрын
I think useRef should be used for forms, you don't want component re-rendering on every key stroke just for a form, but if you was using a search/filter input where you are filtering on the users key stroke then you would need to useState and make it a controlled component.
@chonmon
@chonmon Жыл бұрын
@@CraigClayton-bk3ze It only re-rendered the input DOM tho? Instead of the whole form if I understand it correctly. I don't think it's a big deal.
@ccrsxx
@ccrsxx Жыл бұрын
@@chonmon yes, not to mention you'll always want to have some kinda validation on the form.
@CraigClayton-bk3ze
@CraigClayton-bk3ze Жыл бұрын
@@chonmon it's not a big deal but if you can avoid any components from rerendering no matter how small is just a bonus. Also it's less syntax in that component, which looks nicer
@thienhuynh7962
@thienhuynh7962 Жыл бұрын
@@CraigClayton-bk3ze then you can opt for other event like submit or blur to minimize re-render. Although useRef is a fine solution since there’s no re-render, using it with forms that have many fields or require validation will give you a hard time managing these fields’ value and their behaviors
@jennifermagpantay7933
@jennifermagpantay7933 Жыл бұрын
Golden tips! Love content like that with different case scenarios and clear explanation! I have learnt so much! Thanks for sharing!
@runonce
@runonce Жыл бұрын
For handling form why not simply grab the input values from the onSubmit event? No need for state or refs.
@twothreeoneoneseventwoonefour5
@twothreeoneoneseventwoonefour5 Жыл бұрын
Yes that is what I usually do. const formData = new FormData(e.currentTarget) and then const [username, password] = [formData.get("username").toString(), formData.get("password").toString()]; looks cleaner to me than using refs or state there well I still use state for input validation though
@deadlock107
@deadlock107 Жыл бұрын
It was worth to watch, I learned pretty valuable things especially the fetch abort, it's golden, thank you!
@bowenp01
@bowenp01 Жыл бұрын
Fantastic! I’m just learning react and you’ve explained the funky behaviour I’ve been getting with useState perfectly. Thanks for taking the time to make these videos 😊
@rubyvi7308
@rubyvi7308 Жыл бұрын
Why are you excited to watch while the other crying are u happy
@belkocik
@belkocik Жыл бұрын
amazing video for react beginners. :) Thank you. Looking forward for more react mistakes that beginners and more advanced devs make
@kuken72
@kuken72 Жыл бұрын
This was really straight to the point and very helpful. Thank you Kyle! :)
@nsontung
@nsontung Жыл бұрын
one of the best React tips I ever learn on KZbin. Thank you so much
@adnanhaider9302
@adnanhaider9302 Жыл бұрын
The number of useEffect gotchas and permutations are just never ending. I have such a love hate relationship with this hook.
@coderyan
@coderyan Жыл бұрын
You and me both
@Toomda
@Toomda Жыл бұрын
This was soo helpful. I had a beginner project, just for fun and I almost made all of the mistakes. I just fixed my code, and it looks much better now. Thank you
@vaibhavsri.
@vaibhavsri. Жыл бұрын
Really useful one. Please keep on making great informative videos like this. You're the best!
@jackwin9641
@jackwin9641 Жыл бұрын
well this is what I am looking for ages. THANKS KYLE, you made my day, now I can revise my old code at a higher level
@pedrocruz8164
@pedrocruz8164 Жыл бұрын
some of the senior developers in a company I worked for used to not approve my PRs asking for me to not use useRef to the store any state in react component. It is nice to see someone explaining why not every state needs to be rerendering the component on every data update.
@CarlosRenanFonsecadaRocha
@CarlosRenanFonsecadaRocha Жыл бұрын
A good thing to point out about the first mistake is that a good UX informs the user if the field has any errors while they are typing; in this case, this is not possible. Better to stick with states, but it is a nice thing to know.
@asmmisfar
@asmmisfar Жыл бұрын
Hey Kyle, This is really very helpful for me. Tomorrow I have a task to complete in my office. I was worried about how to do that. but, this video gave me a clear idea about that. Thanks a lot. Keep going, bro. Loves from Sri Lanka ❤
@WorkThrowaway
@WorkThrowaway 14 күн бұрын
This was a great video and helped me solve an issue i had with my hook, namely having multiple states update with an action needed once they were both updated. it took a while to wrap my brain around it, but this video really helped give me the vision. love your videos and that you go super in depth (in the longer ones). probably the best coding tutorials on youtube. if i ever get my web dev dream job, i will be getting you a few coffees/beers.
@saheedsimisaye8978
@saheedsimisaye8978 Жыл бұрын
Most valuable React tips I have learnt regarding some bad code practices I have been applying in React. Thanks for this very comprehensive video with lots of valuable information covered in just over 20mins.
@michalbilinski4168
@michalbilinski4168 11 ай бұрын
Hands down, what a perfect rhetoric - watched it with great pleasure - thanks
@workwithwegs4541
@workwithwegs4541 Жыл бұрын
Hey Kyle! Thanks a lot for your awesome videos! Have you tackled about using normal function and arrow function in react js? You seem to use both but I'm not sure what your criteria is. Hope you make a video about it! Thanks!!
@kamelnazar-instructionalde9740
@kamelnazar-instructionalde9740 Жыл бұрын
This worked incredibly well! I can finally play it thanks
@User36282
@User36282 Жыл бұрын
You really have a talent for education my man. Whenever I'm not understanding something in web dev now I just search for web dev simplified and boom there's always a video on it. Thank you! These were really good tips for those of us just getting into front end :)
@mariumbegum7325
@mariumbegum7325 Жыл бұрын
Really good video, very informative and explaining in a clear way.
@darkmift
@darkmift Жыл бұрын
Excellent explanation on state setter usage
@DarkFlarePrince
@DarkFlarePrince Жыл бұрын
This is the single most useful video I've seen since I started React coding
@ori-kapkap
@ori-kapkap Жыл бұрын
It's very helpful for React beginner like me! Thank you for your videos :)
@Caspitein
@Caspitein Жыл бұрын
Interesting video Kyle! I noticed I do make a few of these mistakes myself. I think the problem is that us developers can be a bit "lazy" learning new frameworks. I understand how the useState and useEffect hooks work and I never took the time to learn about useRef and useMemo for example.
@coderyan
@coderyan Жыл бұрын
totally!
@Spyrie
@Spyrie Жыл бұрын
You'll use it once you handle big data and use expensive functions that can block the main thread
@d.ilnicki
@d.ilnicki 10 ай бұрын
Well I this case the "lazy" one is the video author. Recommending using refs over state on 1.34M subscribers is a crime.
@paulbird2772
@paulbird2772 Жыл бұрын
Very clear video, I just switched to Typescript for last major project, took a bit of effort initially but rewards are great, the build step catches a good few errors very early. I think not using TS could be added to your list. I expect many that haven't given it sufficient time will disagree.
@dannyj7262
@dannyj7262 Жыл бұрын
I spent hours on my degree final project sorting out errors that js didn't pick up until I tried to run a piece of code with an error in. Switched to TS and it's a million times better and Id also say I've learnt a lot more too
@habibiSD
@habibiSD Жыл бұрын
Well done sir, excellent video. Thank you for your hard work.
@loicrutabana1884
@loicrutabana1884 Жыл бұрын
Amazing! You make great content. I especially like your youtube shorts
@movsesaghabekyan9794
@movsesaghabekyan9794 Жыл бұрын
It was amazing man. Thanks a lot🔥🔥
@mingxindong3150
@mingxindong3150 Жыл бұрын
that just makes so much sense!!!! thank you for bring the good code
Жыл бұрын
You just prevented some lay offs, great job.
@noelfrancisco5778
@noelfrancisco5778 Жыл бұрын
great tutorial, I learned something new today. Thanks :)
@user-ol6tq5hw7s
@user-ol6tq5hw7s Жыл бұрын
Phenomenal video Kyle, I like this video of yours the most where you show the best practice and where you point out mistakes that are often repeated, so I can't wait for another similar video and keep it up. Big greetings to Serbia! :)
@marwenlabidi1038
@marwenlabidi1038 Жыл бұрын
thank you for this great quality content
@KathidFX
@KathidFX 11 ай бұрын
It does work as the same as before in case of email and password, but we use usestate , value and onchange to create Controlled components. Uncontrolled components with refs are fine if your form is incredibly simple regarding UI feedback. However, controlled input fields are the way to go if you need more features in your forms.
@developer_hadi
@developer_hadi Жыл бұрын
Thank you so much, as a beginner you helped me a lot
@louis-emmanuelisnardon8308
@louis-emmanuelisnardon8308 Жыл бұрын
Great video ! Well explained ! Thank you, I'm modifying my code right now...
@sergiogusto
@sergiogusto Жыл бұрын
00:45 tag stores fields value
@taulantus
@taulantus Жыл бұрын
For the first case you don’t need state or refs the onSubmit function has access to all the input fields via the event parameter
@mehmetacikgoz9814
@mehmetacikgoz9814 Жыл бұрын
Using refs instead of state does not seem right in this scenario. First of all, such a render does not create any overhead since behind the scenes react will do equivalent of what you have done with refs. Besides, these code will probably be improved with validators etc. which will result going back to state version
@rvft
@rvft Жыл бұрын
Sus lan
@neutralface
@neutralface Жыл бұрын
You're correct. React has always preferred controlled components (react handles input value) over uncontrolled components (DOM handles input value). This is second time I see Kyle making this counter-argument to use refs, which I think is incorrect.
@ACMonemanband
@ACMonemanband Жыл бұрын
This is really debatable, as the scenario Kyle mentioned is that, all the inputs are only used upon form submission. For experienced React developers, we have always been using controlled components and get really used to it, so we are very unlikely to use Kyle's uncontrolled ways in any circumstance.
@neutralface
@neutralface Жыл бұрын
@@ACMonemanband True. Refs are mentioned in the "Escape hatches" section in the new react docs, which for me intuitively tells that refs are used as secondary option when first option of controlled components doesn't work.
@rand0mtv660
@rand0mtv660 Жыл бұрын
​@@ACMonemanband These days I usually just use react-hook-form and don't worry if something is controlled or uncontrolled in a most forms. The fact is that for more complex forms that might compute a lot of stuff, uncontrolled form inputs are better because they won't re-render the whole form on each input change. If you need to do any active validation, you'll probably have to go for controlled forms because you'll have to react to form changes all the time and not just on submit, but in cases where you just need to validate on submit, you probably want to go for uncontrolled inputs. Only reason I dislike his input ref example is because you'll rarely only work with two field forms in the real world and you'll most likely have multiple (more complex) forms in your app. At that point, just reach for something like react-hook-form and never worry about building forms in React.
@mikeonthebox
@mikeonthebox Жыл бұрын
I'm thankful I found Svelte and don't have to deal with this complexity. Svelte makes everything so much intuitive. Like yes, there are still some special cases and implementations where you require some special syntax, but for the most part it's just writing regular JS without having to think what wrapper you need.
@mikejuli8243
@mikejuli8243 Жыл бұрын
Man, using setCount( (count)=>{count + 1} ), it's the greatest way how to handle this real react problem! That's was extremely beneficial for me !!!!! Thank you!
@evrentank6402
@evrentank6402 Жыл бұрын
Thanks a lot. These are very important and useful knowledges.
@nigeryanes1987
@nigeryanes1987 Жыл бұрын
Excellent video, thank you very much.😊
@Infinizhen
@Infinizhen Жыл бұрын
Great video. I don't know what more can i say. Cheers!
@igorkushnir4966
@igorkushnir4966 Жыл бұрын
last one just perfect! thanks!
@crim-son
@crim-son Жыл бұрын
This is really helpful ❤️
@ethanmcrae
@ethanmcrae Жыл бұрын
I really appreciate this video!! 🙌
@MaherOmri
@MaherOmri Жыл бұрын
Amazing explanation! Many thanks
@wisdomelue
@wisdomelue Жыл бұрын
best explanation of useMemo out here👏🏽
@carlosricardoziegler2650
@carlosricardoziegler2650 Жыл бұрын
Good tips , thanks for sharing
@joemathan6101
@joemathan6101 Жыл бұрын
You would still control re-renders by using denounce on top of state. So, there won't be a need for ref in this case. As the react doc itself suggests us to go with controlled components over uncontrolled components Useful video thank you
@joseff5998
@joseff5998 Жыл бұрын
I really appreciate your explanations. Top-notch!.
@shivshankarshejwal6728
@shivshankarshejwal6728 Жыл бұрын
Nice tip last one.Thanks
@mangman
@mangman Жыл бұрын
Great video! useRef seems neat, but you do lose the ability to have real time validation, as that logic would be placed in the onSubmit function.
@nirmesh44
@nirmesh44 Жыл бұрын
best tips ever. i also was not using functional way of setting state
@youssefhossam9077
@youssefhossam9077 Жыл бұрын
that was helpful thank you
@yashpreetbathla4653
@yashpreetbathla4653 Жыл бұрын
Great video dude thanks :)
@vorkosiganhs
@vorkosiganhs 6 ай бұрын
Amazing video, thx a lot!
@appuser
@appuser Жыл бұрын
This video rocked my world. Had quite a REACTion to it.
@raziechavoshi5994
@raziechavoshi5994 Жыл бұрын
super informative and helpful
@singhsankar
@singhsankar Жыл бұрын
very simple and very useful!
@gilsonconceicao5201
@gilsonconceicao5201 Жыл бұрын
Thanks. I didn't knew these.
@NathanBudd
@NathanBudd 8 ай бұрын
That last useFetch insight is very helpful! I think it could be even more so if combined with some king of debounce? So the fetch only runs after say 0.5s?
@mystic7207
@mystic7207 Жыл бұрын
Awesome explanation ❤
@maximpolsky2683
@maximpolsky2683 Жыл бұрын
Many thanks! Good luck with your channel! Greetings from Kyiv!))
@tomasburian6550
@tomasburian6550 Жыл бұрын
You are my hero. Btw, I think that we all learned the hard way that adding the useState count twice in a row would still do it just once :P
@charlesvicencio2461
@charlesvicencio2461 Жыл бұрын
Thank you Kyle!
@AR7editing
@AR7editing Жыл бұрын
15:45 in that case instead of useMemo we can directly use in the dependency array person.name and person.age and it will not cause rendering when you change the dark mode checkbox
@ode2877
@ode2877 Жыл бұрын
Usefull for beginner like me, thanks 🎉
@RiteshNEVERUNIFORM
@RiteshNEVERUNIFORM Жыл бұрын
In the last one we can also use debounce custom hook. That way we can use it everywhere
@MrQVeeBoo
@MrQVeeBoo 11 ай бұрын
Very good, on point, thx
@chanhaoen62
@chanhaoen62 Жыл бұрын
Thanks for all the react tips! Really helped me a lot :) will you ever put out a video of you playing guitar? haha
@lukas.webdev
@lukas.webdev 11 ай бұрын
I'm pretty sure, that there is already a part in one of his videos, where he plays a solo... But I can't remember how it was called... 😄
@user-cp4wf4xy1g
@user-cp4wf4xy1g Жыл бұрын
Simple and brilliant
@mr.gandalfgrey2428
@mr.gandalfgrey2428 Жыл бұрын
Soo good to see that there's finally more than just a guitar in your room :D just kidding, awesome video as always!
@sam-u-el
@sam-u-el Жыл бұрын
thank you sir what was informative
@darkthrongrising5470
@darkthrongrising5470 Жыл бұрын
I've been tinkering with React here and there for about five years, this is the first I'm hearing of a functional version of useState.
@FrancisBourgouin
@FrancisBourgouin Жыл бұрын
Pretty great tips for React! However, I have a couple of disagreements with your mistakes. Maybe I'm wrong, but I'd be curious to discuss with others here: 1- useRef vs useState for forms: Using state to update and rerender form inputs is what a controlled form is. If you use useRef you can't apply conditions or mutations on the inputs, you'll trust your DOM into having the right information instead of your state. So even if it works, if you need a form, use a state, not a ref. 2- prev vs count: I disagree with using prev everywhere, especially with the example that you're using. When I use count, I know what count is, all the time. if I use prev, I need to look through my entire code between the state and my function to 'count' how many times did I call setCount. Also, you should do all the work, then call a setState, not do a setState party in my opinion. Continue the great work!
@saikatpaul6576
@saikatpaul6576 Жыл бұрын
Learn the basics dude.. What he did with the count is exactly how you should do it
@FrancisBourgouin
@FrancisBourgouin Жыл бұрын
@@saikatpaul6576 Very productive comment there, care to elaborate on why I'm wrong ?
@saikatpaul6576
@saikatpaul6576 Жыл бұрын
@@FrancisBourgouin you might need to setState on numerous conditions.. How are you going to do that? The way you are talking about is not possible because that way you can use setState only once. Say it's an array of object. And you may want to manipulate it on different conditions
@FrancisBourgouin
@FrancisBourgouin Жыл бұрын
@@saikatpaul6576 I would disagree with what you just said, there's always a easy way to do it with one setState. I'd be curious to see what you would find impossible to do, I'll show you how I would write it.
@saikatpaul6576
@saikatpaul6576 Жыл бұрын
@@FrancisBourgouin it's not impossible.. But that's the right method..
@MJstart
@MJstart 10 ай бұрын
Thanks for video Kyle
@g_sami__newn8728
@g_sami__newn8728 Жыл бұрын
Useful video❤️
@sagarmishra6746
@sagarmishra6746 Жыл бұрын
I even express with words how much this video has helped me. I got answers to lot of my questions. Thanks Kyle💥
@eiatot6455
@eiatot6455 Жыл бұрын
{} === {} false is the correct result for more than one reason but what I want to stress is that {} is NOT an object, it is the LITERAL CONSTRUCTOR hense don't tide the symbols to what they actually are, the constructors return objects. Excellent video ty.
@jesuscabrita5815
@jesuscabrita5815 Жыл бұрын
that useMemo trick... was lovely
@AllAboutDev
@AllAboutDev Жыл бұрын
Last tip was really important ❤
@anhqui19822011
@anhqui19822011 2 ай бұрын
Thank you for the great video! Regarding the choice between useRef and useState for form submission, I believe we should use useState instead of useRef. This is because we typically need to reset the input value to empty after submission. For input filtering, updating the state as the keystrokes change is necessary to display the latest value in the UI.
@sandhilt
@sandhilt Жыл бұрын
Thank you for share.
@beinghappy3924
@beinghappy3924 10 ай бұрын
You really deserve thumbs up from me. Good Job. 👍
@jessejoseph2643
@jessejoseph2643 Жыл бұрын
Thanks Kyle. Funny how I'm an advanced react developer and I make a couple of mistakes you pointed out.
@radhouze2554
@radhouze2554 Жыл бұрын
Subbed for that beautiful Jackson guitar
@jeromealtariba7339
@jeromealtariba7339 Жыл бұрын
excellent ! Big thanks
@mustaphasalehipourenglish7387
@mustaphasalehipourenglish7387 Жыл бұрын
was great like always
@shashi20008
@shashi20008 Жыл бұрын
Well, like others in the comments have pointed out, useRef over useState shouldn’t be taken as a general rule. Aamof, for the example discussed in the video, it might be best to leave the inputs as uncontrolled components if their values are not explicitly used. The FormData API can be conveniently used in the submit event handler to get access to actual values at time of submit. That said in non trivial examples it’d typically not be the case as you’d want client side error handling and what not. Just use useState then. Also regarding the last suggestion in the video, the behaviour described for AbortController is not accurate. Aborting a request using AbortController doesn’t prevent the promise returned from fetch() call from settling. The promise will actually be rejected with DOMException having code ‘AbortError’. While cancelling previous requests in this manner you’d want to explicitly ignore these errors (and not display them to users as error). An alternate method I have used to solve the same problem is to keep track of start time of the current request (via closure), and start time of most recent finished request (via ref). When a response arrives, check it’s start time against most recently finished request’s start time, if it’s not later just ignore the response. Sounds complicated but can easily be wrapped in a small lib function.
@achyutrastogi8080
@achyutrastogi8080 Жыл бұрын
Is there any inherent benifit to using your mehod over useMemo the way Kyle has shown? The only downside I see is having to manually ignore code 'AbortError' DOMExceptions so that they don't clutter your health tracking tools.
@hazemalabiad
@hazemalabiad Жыл бұрын
You are AMAZING ... Kyle 💐
@elmalleable
@elmalleable Жыл бұрын
if its a simple form then you can just take the values from the form event when you submit and you dont really need to keep state provided you have a vary basic use case for the form, complex validations and connected models then you'll probably go back to using state
@it9hektar
@it9hektar Жыл бұрын
good explanation !!!, my problem can be solved, thank you very much..
@khallikan
@khallikan Жыл бұрын
Damn what a great video. Excellent at explaining
@backupmemories897
@backupmemories897 3 ай бұрын
hmm I don't have this problem in angular xD but i'm trying to learn react this month. this is a good help
@sheriffawzy2998
@sheriffawzy2998 Жыл бұрын
Good work Kyle 😉
@komalmadamwar710
@komalmadamwar710 Жыл бұрын
this is super helpful
Most Beginner React Developers Do This Wrong
13:47
Web Dev Simplified
Рет қаралды 220 М.
Why Signals Are Better Than React Hooks
16:30
Web Dev Simplified
Рет қаралды 441 М.
Что будет с кроссовком?
00:35
Аришнев
Рет қаралды 2,5 МЛН
ISSEI funny story😂😂😂Strange World | Pink with inoCat
00:36
ISSEI / いっせい
Рет қаралды 13 МЛН
CAN FOXY TRICK HIM?! 🤣 #shorts *FOXY AND NUGGET!*
00:17
LankyBox
Рет қаралды 19 МЛН
Этого От Него Никто Не Ожидал 😂
00:19
Глеб Рандалайнен
Рет қаралды 9 МЛН
Learn TypeScript Generics In 13 Minutes
12:52
Web Dev Simplified
Рет қаралды 195 М.
You might not need useEffect() ...
21:45
Academind
Рет қаралды 129 М.
10 Tailwind Classes I Wish I Knew Earlier
13:31
Web Dev Simplified
Рет қаралды 150 М.
Junior Vs Senior Code - How To Write Better Code As A Web Developer - React
21:48
All useEffect Mistakes Every Junior React Developer Makes
22:23
Learn React With This One Project
42:38
Web Dev Simplified
Рет қаралды 667 М.
3 React Mistakes, 1 App Killer
14:00
Jack Herrington
Рет қаралды 112 М.
Has Generative AI Already Peaked? - Computerphile
12:48
Computerphile
Рет қаралды 220 М.
Beginner React.js Coding Interview (ft. Clément Mihailescu)
36:31
Ben Awad
Рет қаралды 2,1 МЛН
Что будет с кроссовком?
00:35
Аришнев
Рет қаралды 2,5 МЛН