useEffect with dependency array triggers multiple times because of array.map - reactjs

I'm creating a simple React application where a parent component renders a number of children components based on an input range slider (using array.map).
I'm performing certain actions within a useEffect with a dependency array in the child component (particularly, I'm obtaining a 3D model's bounding box size using react-three-fiber). Even though I have the dependency array, I can see from the console logs that the useEffect executes each time I move the slider.
How can I ensure that this useEffect only executes once? I was considering passing the useRef of the model to the parent and doing the useEffect actions there, but I'm curious if there's a way to modify useEffect such that it just executes once.

After a deep understanding of my needs, one of the arguments was changing.
Functions not through a useCallback will always change. Rebuilt objects (and to some extent, arrays) are new as well (unless memoized).
I checked what is changing first. Instead of using useRef, figure out what is changing in the data.
But in reality, if that dependency was actually needed, I can memoize it (e.g. useMemo) instead of just removing it.

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.

Reason to use useMemo in react js

In my react js application i have a reduce function that is responsible to loop trough an array of 4 strings and to return a string with all these items. Is there a reason to wrap the function with useMemo hook or it is redundant in this situation?
useMemo caches the result of the given function so It's not recalculated on every re-render.
Whether to memoize depends on how often the function's dependencies change. Still it's unlikely that you need to recalculate the value on every render, so generally its a good idea to wrap it with useMemo

React useEffect/componentDidMount vs. state hook + function

It seems to me that one could replace useEffect/componentDidMount with a state hook and function components. For example, if I wanted to make a fetch in useEffect or componentDidMount, I could simply create a function component that rendered the component that needed fetching, add the fetching method in the function (which will execute upon rendering) which modifies a state hook (so that once the data arrives, the page will re-render with the data). Since React has selective rendering, any other part of the function component that gets updated won't cause an unnecessary fetch.
Am I correct in saying this? Are there any other specific instances where useEffect/componentDidMount is strictly better?
Am not sure why you want to replace componentDidMount in class component or useEffect with a custom function for the use case you highlighted but those two are different in terms of behavior, componentDidMount is one functionality that useEffect provides in function component. useEffect is a combination of componentDidMount and componentWillUnmount and you can have mulitple useEffect on one function component. useEffect accept array of values that could make it run again, all you do is specify those value for that particular useCase you wanted and whenever that values changes the useEffect is called, for UI changes you attach your useState to your logic and if followed accordingly you wont get unnecessary fetch request, if you want useEffect to be called just once then attach just an empty array like this useEffect(()=>{//your fetch logic here },[])

when should I use useRef or useState in reactjs

Now I'm on changing class based component into functional component, and there's instances which I should determine to use useRef or useState.
I already tried to get my answers using stackoverflow Q&As, it keeps me wondering.
What I understood is useRef and useState keeps value during whole apps, and useState cause rerendering and useRef is not.
we needs rerendering process if there's some changes in view, If so, Should we create whole variables with useRef which is not in return( <> ...</>)> ?
Generally Ref is used when you dont want to component re-render again but you want value in some form so that you can use later. In layman term if you just want to play with dom related stuff like updating width, height etc.
Common example for using ref:
When you want to focus in and out your input without using state(as you dont want to render the component again)
Updating dynamically style(Fox ex: You create your accordian then you want to update heigh and show transition when according open and close(if you dont want to show you can avoid this example))
If you want to create this type of utilities then you dont need to play with states you can do only with ref
for most use cases you want to handle your react component's behavior through state provided from useState (or props where you get as parameter). that's the React way to go.
eventually there will be cases to useRef, where you may need for example to access a DOM element directly for some special reason. but they are exception cases. if you you see yourself calling useRef throughout your application you are most likely doing something wrong.

What is the use case of useMemo in React?

I need help to understand when to use useMemo hook in React vs useState + useEffect. From what I've understood after reading other questions on S.O. and websites :
With useState you can create a value (changeable through the setter) and you can use useEffect to do whatever you need if some of the dependencies listed in the dependency array changes. On first render for example your component will be rendered with the initial value passed to useState, then the effect will run and your component will re-render with the new value you set with the setter in your effect.
With useMemo you can create a value that will be computed from a function you give to the hook and it will change if some of the dependencies in the dependency array changes. So far, to me, it looks like useState + useEffect except you don't have the setter to change the value. On render your useMemo will run if one of the dependencies has changed. Difference here : your component will wait for the value to be computed before rendering (not sure about this part).
From what I've read, useMemo should be used for heavy operations. But if it's blocks the rendering of the component what's the point ?
Some says that with the dependency array you can avoid unnecessary updates but I can also do it with useEffect without blocking the render ? If I don't have a heavy component to render, isn't it faster to use useEffect ?
Thank you :)
Edit :
I accepted Philip Feldmann's answer as it fits my needs. As suggested in the comments you can take a look at this question for a global comparison :)
You are correct, useEffect runs after rendering as a side effect. That means that when you don't want to block the render loop, you can use your version.
That version will however trigger another rerender through calling the setter.
The initial time to paint might be faster, but you'll instantly block the render loop again by setting the new value, which in most cases should be slower than just using useMemo directly.

Resources