Is useEffect inside custom hook considered a bad practice? - reactjs

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 !

Related

UseEffect: why is fetching data considered a side-effect but not accessing window.location?

I always thought of a side-effect as a read or write operation that is performed while rendering a functional component, and that accesses resources outside of those provided as props. Sort of like the definition of a pure function.
So when I needed to read window.location, I figured it had to be in a useEffect. Turns out the linter doesn't require that window.location be a dependency, so I guess it's ok to access window directly. This means my mental model of a React side-effect is wrong... But why?
If merely fetching data (which is a read operation) is considered a side-effect, then why isn't window.location?
So now I'm wondering, are functional components actually not really pure? Are they only "write pure" but not "read pure"?
How the useEffect or any other memoizing hooks(useCallback, useMemo,...) work works is:
Component re-renders
The dependency list is looked through to detect changes in any of them
If a change is detected, the function inside the useEffect is called
The issue with window.location or any other outer scope variables is that they do not initiate a component re-render to begin with.
This is the exact message on ESLint
Outer scope values like 'window.location.href' aren't valid
dependencies because mutating them doesn't re-render the component
And to answer your question, yes and no.
According this article :
A React component is considered pure if it renders the same output for
the same state and props
So if you add a dependency to an outer scope variable like window in your component, you can't call that component pure anymore.

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.

How to use React Hooks with multiple API calls?

I'm trying to understand how to use React Hooks in my new project and I'm looking for some guidance as I didn't find clear answer.
I have a form that requires data from 3 separate API calls. Currently I have created 3 hooks like useGetDataSource1, useGetDataSource2 and useGetDataSource3 that wrap API calls with useEffect. Also I've encapsulated usage of these 3 hooks in additional hook called useGetSettings with additional useEffect to separate this logic from form code. Is that correct? Or maybe I should create only one hook useGetSettings and keep data source logic separated in plain JavaScript functions?
I want to save data from this form when user presses Submit button. Should I use useCallback for it or I shouldn't use any hook at all? Currently I've created 4 hooks just like with getting data, but without any useEffect/useCallback.
useEffect is meant to control the side effects in functional components, in most cases; you shouldn't need to have a useEffect hook inside a hook that encapsulates another hook that uses useEffect
Most hooks are meant to set and get, for example:
useState hook can be used like:
const [count, setCount] = useState(0);
count is the variable you use to get the current state value
setCount is the setter; where you set the state value
Hooks are cool but do not hookify everything, check this article:
React hooks: not magic, just arrays
If you'd like to outsource complicated logic to another file and call it a hook; technically you may, but it's best to just call that functional, object oriented programming with separation of concerns, write tiny functions that does one thing, one thing only and does it perfectly, this way; when your code grows, your tiny functions will be easy to maintain with the power of emergence.

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.

When to use stateless and statefull components in ReactJS after Hooks changes?

So, i know the difference between the two but after hooks i'm kinda confused about when i should use stateless and when use statefull.
When i was learning the basics of React i was told that stateless is the "dumb" function and statefull is "smart". And that i should use stateless in simple things, because props are imutable and also use more than statefull. I dont really know the difference with Hooks changes in 16.8.
I know that we can use setState now but i dont understand it totally.
This is a great question, and one that I think people will have trouble with for a while. The way I see it, the term "stateless" has been dropped from regular component verbiage and they are just called "functional components".
The concept of "stateless" is still very important though, because it involves no inner state that does not mimic its props. As you said, they are dumb. Generally, if a component can be stateless, it will be more performant. Components that are rendered in loops with a high count do much better with this type of structure. On the other hand, don't stress too much about performance until you're hitting bottlenecks, which shouldn't happen until you've got thousands (or more) of components rendering at once.
To address hooks- they allow you to "hook" into the state and lifecycle of a component. As you will see in the docs, they do not offer more functionality, but a simpler API. This leads to cleaner code and more reusable custom hooks.
If you are dabbling with hooks, maybe try it on some new components you need to build. I've found it to be fun and simplifies my code considerably.
As a final answer, I would say that the concepts of "stateful" and "stateless" components is the same. Only the API that allows you to utilize state has been changed.
Your 'dumb' components should remaing dumb.
Your 'smart' components, can take advantage of hooks to make them 'dumb' with a hint of smart.
Imagine a component where you have to make it 'smart' because there is a toggle in it.
With the old way, you would create a component that has State.
With hooks, you can create a dumb functional component, that just happens to use the hook useToggle.
This keeps your code simple and concise, while at the same time keeping the same functionality you used to have building smart components.
Hooks are just another means to use state (and other functionality) in a so-called "smart", functional, component. That said, their existence doesn't change the answer to this question (of which, there are many).
One example of an appropriate use of state is when you have a component that will render different output based on some sort of change to the component after the initial render. More specifically, if you have a component that needs to make a network call to fetch some data for display, you could use state to keep track of the initial non-existence of that data and update it when the network call returns using setState.
In my experience, as a general pattern, you should use state for things that change and props for things that don't.
I think, the question is actually simple, when do we use the state hook in react? The answer is, if you write a function component and realize you need to add some state to it, now you can use a state hook inside that existing function component. Previously you had to convert it to a class component.
Then why don't we use the class component from the beginning instead of function component? Because when it was first introduced, the recommended pattern for react developers was to use as many stateless components as possible, in other words as many function component.
And in my personal opinion, the function component is neater and easier to use, maybe even more suitable with the reusable component concept. So then, yeah, now we can expand the use of the function component even more.
Hope it helps

Resources