The order of react hooks - reactjs

I am trying to understand how React hooks work reading official docs:
https://reactjs.org/docs/hooks-rules.html
And there they say that react relies on the order hooks are called. I still don't get why the order is of importance and why a hook placed in a conditional will cause bugs, could anyone explain?
Particularly this sentence makes me confused:
React wouldn’t know what to return for the second useState Hook call
why?? Does react somehow binds useState with useEffect?
Then, this question:
So how does React know which state corresponds to which useState call?
From my understanding there is only one state, so why they are talking about states (plural)?

Related

Is it fine if useContext has many useState in React

I am working using useContext in React. Today, I recognized that I am using too many useState in useContext. I was looking for the answer, but I could not find it.
I know it is a silly question, but please answer my question if possible.
Thank you.
Thank you for the answers to my question. So, I understand that if there will be many states in useContext, it is a good way to use useRedux.
This is my opinion. I think there is no such thing as too much as long as your states are relevant with what you are doing. It depends on what is your purpose when using the createContext. But make sure to organize them well so that they are still modular and not mixed with other context of states.
For me, I draw a simple borderline where if I'm only making some one-off reusable components that need control from far away (e.g. Dialog which can be toggled by deeply nested button), then I should create a context that has just enough states for that component. Whereas if I want to store some states which I want to access from multiple places, especially if it is related to business logic, then I prefer to use Redux instead.
I think useContext and useState are different functions:
useContext: This is a hook that returns values from the context that has been kept. Any change in values causes the react component where this hook is placed to rerender.
useState: a hook that declares the react component's state.
I think I understand what you mean when you say you declare many states in the context. Some best practices you need to consider are:
Using useReducer hook to group & manage the change of states. It makes it easier to control the changing of states. It is obvious that the state shifts with each individual action.
You need to review the total state that is declared. Only keep states that need to be shared in that context.
Refer: read more in react js docs about context api & declare a state in react component.

Is useEffect inside custom hook considered a bad practice?

I was trying to create a reusable hook which includes 2 other mutation hook from react query which does 2 different operations. I was successfully able to create my custom hook and everything is working as expected. My only question is, while building the hook I had to use a useEffect inside my custom hook. I am just wondering if it is a bad practice to have a useEffect inside a custom hook and do I need to change my approach? Will there be any performance issue because of this? Is there something I should be aware of?
It's a very common thing to do. The official documentation describes a custom hook that uses useEffect.
The only thing you should be aware of is that, as always, your hook isn't supposed to intentionally break hook isolation by maintaining an arbitrary shared state outside the hook itself.
I think the "intentionally breaking hook isolation by maintaining an arbitrary shared state outside the hook itself" refers to what happened to me. I was storing a "variable" in the custom hook (with useState) but I was wanting that variable to be accessible in the outside React component, but sometimes the custom hook state was reset, so that value was also reset, and the React component would have suffered from this.
I think the general idea is to always maintain order, you define state in the outer hook/React component, pass that state into custom hooks, the custom hook can generate other data that can be returned as after some processing steps (like with useEffect) and the data can be used in the outer hook/React component as a "state generated by some initial state" which is persisted ONLY in the outer hook/React component caller.
So, in your case and mine, NEVER initialize & maintain an outer hook/React component caller state in the custom hook or NEVER modify the initial state given by the outer caller, in your custom hook.
Sorry, it might be confussing what I wrote, but this is still not very clear for me too. Hope it is clearer though than the short answer Igor gave you.
Good luck !

Should useEffect be used to get derived state from props

I read How to sync props to state using React hooks : setState() that is basically about how to mimic getDerivedStateFromProps in a functional component. The accepted answer said to use useEffect. But the problem is that this would cause an extra unnecessary render, as some comments pointed out. So I wanted to ask a separate question about specifically whether useEffect should be used in this case.

react custom hooks vs normal functions, what is the difference

I'm trying to wrap my head around custom hooks. I understand normal hooks which is just fine, but my question is, when writing a custom hook, what is the difference between that and a normal function? I mean why not call it a normal function instead of calling it something like use*
I believe no one has answered your question exactly. I'm still also understanding the benefits and purpose of having this extra feature called hooks, but I can still share my understanding.
React Hooks are JS functions with the power of react, it means that you can add some logic that you could also add into a normal JS function, but also you will be able to use the native hooks like useState, useEffect, etc, to power up that logic, to add it state, or add it side effects, memoization or more.
So I believe hooks are a really good thing to manage the logic of the components in a isolated way.
So, you could have a foo.component.js (UI), a useFoo.js(logic), where useFoo will contain maybe many js functions and one hook to manage that functions and return what it's supposed.
This is an amazing video about react hooks, fully recommended
https://youtu.be/J-g9ZJha8FE
There are some differences and problems that make us use react custom hooks:
First of all, if you use normal functions, with every re-render of the component, this function will be created again and it causes the lack of performance. you may think that it can be fixed by using useCallBack and make react not to create a new function every time it re-renders but it is not the main problem that we are going to solve.
The main problem as the react document has discussed with a brief example of tracking online friends, is avoiding copy-pasting the same logic in different functional components which they need to be stateful too.
If we use normal functions inside a component and use useCallBack to avoid creating a new function every time, we did not solve the problem because in every component we should also copy this logic so this did not solve the problem.
The other solution is to make a function outside the functional component to handle this logic, but there is a big problem: in a normal function outside of the component, we don't have access to states because as we mentioned, this implemented logic is stateful and we have access to states only in react components.
So what is the solution here? yes, Custom React Hooks!
It is a stateful function that uses other react built-in hooks (e.g. useState, useCallback etc.) that can wrap around the stateful logic that you wanted to gather in one place and avoid copy and pasting the same logic in multiple components.
With this approach, you can put your logic outside of the component in another function while you are getting the benefit of stateful functionalities of react.
I hope that this answer may solve your problem and resolve your ambiguity.
From the React docs:
A custom Hook is a JavaScript function whose name starts with ”use” and that may call other Hooks. [...] Its name should always start with "use" so that you can tell at a glance that the rules of Hooks apply to it.
So why define custom Hooks with a special "use" naming prefix?
1.) It tells consumers, that these functions are intended to be used with React and obey to an implicit contract (above mentioned rules).
2.) You can have tooling support which checks and enforces these rules. For example, eslint-plugin-react-hooks utilizes a heuristic that assumes, a function starting with "use" prefix and a capital letter after it is a Hook.
React Hooks (custom or non-custom) should start with the use prefix. As well as, as per the React Documentation:
1) Hooks should be called from the React code only not from the Regular JS functions. Hence, Hooks' scope is limited to the React code world and has more power to do a lot with React code. Rather than JS, regular functions could be used across application but as react code guidelines keep the code more aligned to react syntax.
2) In the class-based components, the Hooks won't work but regular functions will.
3) In the regular JS functions, you can't access useState, useEffect, useContext etc. but in react custom hooks I can.
A custom hook depends on one more other hooks. By design React hooks are meant to be used from a component's render method. You will get a warning if you try to use a hook anywhere else. Custom hooks follow the same convention as built-in hooks because they have to be used in the same fashion. The use prefix is just a convention to identify hook functions which are usually call at the very top of a component render method.
You can name your hook function anything you want but as I mentioned, you will get a warning from React if used outside of a render method.
You can call it whatever and it will still work fine. The only advantage is that if you use the “useName” convention, React will check for error whether it correctly follows the rules of hooks. It just makes your task slightly easier.
As other users have stated custom hooks or hooks, in general, are used where we have to do anything related to react component while other util functions are not tied to react state and won't work is areas where react state logic is in place.
An example of custom hooks be useCustomNavigation which could a list of navigator function like navigateToHome, navigateToCheckout etc. So when you to route to homepage from different parts of code, we just use this hook. Also any logic/feature like analytics, and side effects could be part of navigateToHome function.
An example of Util function could be anything like capitalize which does not has to do anything with react or react component. You cannot create a util function called navigator and add useNavigation.
As I see it, custom hooks have their own specific purpose and have their own characteristics and approach.
What I mean is that in certain cases we would want to create a custom hook and not a function.
For example, if you have a need to store some data in the Localstorage you would want to create a custom hook for that and call it "useLocalStorage" and if you want to create a component, let's say a page form, you would want to write a function component.
Difference being that our hook is not a component and shows nothing on our UI.
It is simply a logical operation.
The reason I see them as different other than the "logical" example above is that our custom hooks are unique in a way of allowing the usage of other custom hook related hooks. For example, the "useDebugValue" which can only work in a custom hook.
What is weird to me is the way React differentiates a function from a custom hook, which I think is the main cause of the confusion.
It "checks" your function name and if it starts with "use" then it's a custom hook. What I think would have been a better option is to change the "const" declaration to a "hook" declaration or give it a unique type.
TL;DR, custom hooks are the logic and will allow the usage of hooks like "useDebugValue" and our functions are mostly UI related.

Why use useState over this.state?

I have been learning React hooks lately and I am currently facing useState. I know this is a way to use state in functional components but I wonder what the real benefits are above using a React.PureComponent with this.state?
Is it really bad practice now to use a PureComponent instead of useState or useEffect? Does this make the app "faster"?
I know this question sounds dumb because useState is the new kid on the block but I just need a valid reason to refactor my old components into this new pattern?
Edit: I've been using hooks for a while now and like them a lot (changed my opinion), however it increases the learning curve and there are pitfalls:
Good stuff:
Not wrapping your component in Higher Order Components (looks cleaner and sometimes order of HOCs can cause issues)
Composability and re-use becomes easy - splitting code out to custom hooks is second nature. Also reduces argument for adding other abstraction concepts around state management, data fetching, utilities since hooks can do it all.
No confusion around this (easily avoided with arrow functions in classes tbh)
Some components come out cleaner and terser (but some especially with lots of event listeners can turn into a hot mess without careful architecture and knowledge of how to make the best use of hooks)
Some libraries are hook compatible or hook focused only these days (not a "good" thing but an argument for use)
Bad stuff:
Larger API surface area/knowledge - memo, useCallback, useMemo, useRef, useEffect, useLayoutEffect, useState etc. Ask a beginner how to debounce a callback - suddenly it's a hard problem.
Functions can become unmanageable since hooks have to all be called in them in the same order (note: you can make your own hook with more hooks inside to split things up)
Trading confusion around this for much more problems such as:
Infinite loops when you both read and write to a variable in a memoized hook
Stale data if you didn't list dependencies, also if you didn't then you can prevent garbage collection on any trapped references.
Getting into a dependency hell to avoid stale references (wrapping stuff in useCallback, then "tunnelling" some of the variables in with useRef etc)
Performance degradation since hooks are slower to execute and create, non-hook functions are created every render and also will break purity checks of children, even functions in hooks such as useRef (and I believe useCallback) are quietly created and discarded every render in favour of the first one created.
Testing hooks nested in a function is harder/more complex than testing class methods
Side note: Solid framework has a better implementation of hooks which don't require dependencies
TL&DR: There is no need to refactor all old components.
useState and others react hooks introduce a new way to implement your components. They can be helpful as they simplify code reusability. You can move your specific logic to a custom hook and use it in several components. Custom hooks can call useState and they don't have any possibility to damage state from other useState calls. It allows you to split component logic more wisely.
So there are 2 main profits of using useState: code reusability and code splitting.
When it's better to refactor old components?
Let's say, you have 3-4 legacy components, which make similar things, but it's complicated to reuse code. You can rewrite such components to hooks, move all common logic to custom hook and reuse this hook in all of these components.
Also, if you have any additional questions you can take a look to this https://reactjs.org/docs/hooks-intro.html article
And one important thing: PureComponent equivalent in "functional component world" is to wrap your function with React.memo
useState, this.state and PureComponent are different terms and need not be confused together. As you understand useState is a way of handling state in a functional component whereas you use this.state for a class component.
As far as PureComponent is concerned, it used to optimize renders and you can use React.memo for the same purpose for a functional component.
Also as far as refactoring is concerned, there is no need to do that since Class components will continue to exist and react community recommends you to not refactor the previous code.
I recommend for you to watch React Today and Tomorrow and 90% Cleaner React With Hooks
also, you can read Introducing Hooks
according to using pureComponent, pureComponent is similar to Component which is Class, check classes confuse both people and machines section to understand why functions are better than classes.

Resources