Does `instance` variable cause poor performance? - reactjs

I used a state boolean variable didApiCalled to check whether the API gets called or not.
But I also wanted to use a instance variable for this usecase as instance variable didn't re-render. My colleague thinks this is a bad idea as this will cause some binding issue or it'll throw some error.

Related

Can I use the matching state variable to the state setter function? Ex: setValidateFields(validateFields);

I couldn't find a proper answer for that, but I'd like to know if it is a bad practice or a recommendation related to using the matching state variable to the state setter function.
setMyState(!myState);
It's common to see this approach mainly to change the boolean values to the opposite. So I thought it was normal to do it.
But I'm getting this error from Sonar:
React state setter function should not be called with its matching state variable
When the setter function is called with the state variable as a parameter, nothing will happen. This can happen by mistake when attempting to reset a default value or invert a boolean, among others.
The fix is simple, but I've never seen any warning or official information related to it.
Does anyone?

Is it always necessary to add all used functions within useEffect to its dependencies array?

I am currently building a Tetris game on React just to practice hooks (used to develop in class components back in the day, kind of left React for a while and yesterday I decided to use it once again).
The game is working perfectly well, and it behaves as expected on each and every situation, however, there is a constant warning related to using a function within useEffect without it being a dependency.
To clarify - I have a useEffect function that all it does is call an updateFunction and is dependent just on the x and y coordinates of the moving Tetris block. The update function updates the state of the board whenever the position of the shape changes.
I know that React re-creates functions on each and every render, but giving a useCallback to the update function would cause it to be re-created endlessly (as then, the complier would ask me to make it dependent on the board state, thus each time it updates the board, it'll be forced to be re-created once again), and this causes an infinite loop of rendering.
Is it really necessary to put every function within useEffect as a dependency, even if said functions only causes a visual rendering to show the current state of the game?
You can always put whole function inside useEffect and you want get this error and problem
Someone just asked the similar question, and my answer is there, React won't let me use `useEffect` in a completely reasonable way
The answer to your question is that, no you don't have to, if the warning doesn't bother you, and your code is still working, then move on.
Otherwise you can try to find a way to disable this linter, or ask yourself why not to meet all the dependency requirement.
It's best to think of the effect dependencies as "correct" or not, and not try to tailor them to achieve some specific behavior. (The vast majority of the time anyway)
This means that if an effect uses a value that could possibly change, then it's declared as a dependency. Sometimes you app works fine if your dependencies are "incorrect" because elsewhere you can guarantee a value is constant. But this is more about maintaining the application than having it work currently.
Later if you change how one of the dependencies works in a refactoring, then the effect now may need to re-run and doesn't leading to strange and hard to diagnose bugs like stale values where you can't tell where they come from.
If this leads to cumbersome hooks with huge dependency arrays that infinite loop themselves, then it's an indication that logic is messy and needs to be refactored, split into multiple effects, rethink how the data flows through your hooks, etc.
It's hard to advise specifically without seeing your code. But in your case it seems like you could make the "update function" take arguments instead, which means it could then be completely static. Or if you did use useCallback that depends on x,y then it would regenerate when those change, but you probably have a lot of logic to run when those change, so that's probably expected.
Summary:
I would advise you to take the warnings of eslint-plugin-react-hooks seriously, and clean your code until it passes. In the long wrong, in a large and complex application, it really helps keep things clean.
There are very rare exceptions that come up when doing non standard things, but it's worth it to try your best on this before resorting to ignoring those warnings.

useEffect exhaustive-deps warning: what possible issues is this trying to avoid?

I realize there have been many questions about React's useEffect hook's dependency array, and the eslint warning that may arise from missing dependencies. Some other good discussions about this:
How to fix missing dependency warning when using useEffect React Hook
React useEffect Missing Dependency
React useEffect missing dependecy?
React Hook useEffect has a missing dependency with useEffect
Although the causes & solutions for these warnings are very clear, one thing I'm struggling to grasp is the why. First, to quickly summarize, my understanding is that useEffect as three general purposes:
If its dependency array is omitted, it acts like both componentDidMount and componentDidUpdate: it runs the first time the component is rendered, and all subsequent renders.
If its dependency array is empty, it acts like componentDidMount: it can be used to run first-time initialization code (e.g. fetching initial data from the server, etc).
Otherwise, you can include in its dependency array any variables that you want it to 'watch'; it will act like componentDidMount, and then like componentDidUpdate when those variables change.
(For completeness: its return value can also be used to implement componentWillUnmount behavior, but that's beyond the scope of this issue).
I understand that eslint will complain if useEffect references any functions (or other variables) which are declared outside of useEffect. Per the above links, there are various ways to resolve these warnings: Move the function definition inside useEffect (if nothing outside useEffect needs to call it); add the function to the dependency array & memoize it with useCallback; disable the warning with // eslint-disable-next-line or // eslint-disable-line react-hooks/exhaustive-deps; etc. These all make sense. What I'm struggling to understand is WHY it even complains about this.
So, my specific questions:
Practically speaking, I can't understand why you would ever want a reference to a local function in the dependency array. For example, if you have useEffect(() => { checkCurrentUser() }, []), and checkCurrentUser needs to be defined outside useEffect because it's called elsewhere, checkCurrentUser will be re-defined on every component render (which is why if we put it in the array, we should memoize it w/ useCallback). But to me, it makes no logical sense why one would ever want this in the dependency array at all. So why is this even a warning? What is this warning actually helping to prevent? Throughout all the times I've seen the warning, in every case, the application has behaved exactly as I expected/intended.
If one of useEffect's primary purposes is to 'run once' like componentDidMount, and the way to achieve that behavior is to explicitly put an empty array, why does it hassle you if you specify an empty array? I can understand why it might make sense to warn if you have a dependency array that contains some references but not others - as in 'oops, you forgot some' - but the empty array is a specific, well-defined usage. To me, it doesn't seem to make sense that it would tell you 'an empty array is an issue,' as that's the only way to achieve componentDidMount-type initialization. It feels like the same thing as just warning you "don't use componentDidMount()." Why does it complain about an empty array, if that's supposedly one of the 3 main uses of useEffect?
Again, I do understand the circumstances in which the warning appears, and the ways to resolve it. I just struggle to understand the benefit of even having it, (1) in the case of functions (which we definitively know will change on every single render), and (2) in the case of an empty array (which are a specific usage).
(1) in the case of functions (which we definitively know will change
on every single render)
The reason for requiring to put functions in dependencies
seems to be the same as the reason why they require you to put any other values in dependencies:
what can happen is that a function you are using might be itself referencing some values from component scope, which can become stale.
(2) in the case of an empty array (which are a specific usage).
In this case I will reference answer cited by Dan Abramov from this comment:
I think the biggest gotcha with class life cycle methods like
componentDidMount is that we tend to think of it as an isolated
method, but in fact it's part of a flow. If you reference something in
componentDidMount you will most probably need to handle it in
componentDidUpdate as well, or your component may get buggy. This is
what the rule is trying to fix, you need to handle values over time....
You may find more info on why they did it that way in that thread.

useContext with immutableJS

I have an Object of data that I store as my context. It gets filled with API responses and I feel like performance-wise I'm doing something wrong.
I tried to look into ImmutableJS but there is no reference of combining ImmutableJS with ContextAPI. Is combining them together doesn't give any benefits? And if it does do have an example of to how develop such a thing?
Whether you use context directly, add redux or pass down props through your component makes no difference to how you use immutable. ImmutableJS simply makes sure that an object does not change unintentionally and that it can be checked for changes with fast reference equality.
The problem you describe could arise from the fact that your context object changes whenever any response data is modified. Therefore it would trigger a rerender on all context consumers (see caveats). I like Immutable and use it in a large project, but if I am correct, it won't make a difference, you would have to fix the root cause or handle changes with shouldComponentUpdate.
I suggest you look into redux (or some other context provider) or show us code.
Don’t try solving your problem by introducing a dependency. It won’t be a magic bullet.
From what you describe, your context object changes frequently and is causing your component tree to rerender too often.
Maybe try creating multiple contexts that are only relevant for parts of the app. That way rerenders will only happen with subtrees using specific context.

Reactjs, strange behavior on checking state value (again)

Ok, there is something I don't understand again:
onDateChange(child, performUpdate){
console.log("child", child, child.state);
}
As you can see, from the debugeur, the state has some value. But when I try to access them, they act like if they where not initialized. Like if the setState wasn't an atomic operation after all...
Actually I don't have any idea as it seems counter intuitive.
Can someone help me to get my data from the callback. Every operation in js/reactjs act differently from what it is expected.
Is that because the 'state' property is in another field and duplicated? I can't find any logical reason for this strange behavior.
edit:
So it appear that setState is asynchronuous. And worst part, non atomic operation. This is kind of strange they don't speak of that in the documentation (instead they said to not use state directly but by method call. Why? Because they do the change in another thread without telling the client!!!).
So this is how you have concurrency problem like I had.
Is there a clean approach for this kind of problem? Like a callback on setState method when all the operation are done (some people use delay or inline function, which absolutly don't correct the problem ).
To resolve my issue, I had to use a proxy pattern where there is the datastructure independantly from the view who display it, and act as if it was the same object. So that the controller don't have to deal with all this 'background' threaded operation mess. (Note: the datastructure is not a model, but a readonly object).

Resources