Why doesn't useState function initialize state every time? - javascript

import React, { useState } from "react";
function HookCounter() {
const [count, setCount] = useState(0);
return (
<div>
<button onClick={() => setCount(count + 1)}>Count {count}</button>
</div>
);
}
export default HookCounter;
React calls this function every time when it needs to re-render.
But why doesn't it initialize the state every time?
When exit the function, life of variables is ended, isn't it?
But how does it keep saving values of states?
I don't understand.
In useState function, is there any logic for that?

useState as a function is storing the value you gave it within React's core. When the component re-renders, React is going to pass the updated count from its core to the component.
More information here.

State is initialized only once when you create the component, this is how React works. From the documentation:
What does calling useState do? It declares a “state variable”. Normally, variables “disappear” when the function exits but state variables are preserved by React.
Just to have the context here, let me summarize what is useState and how it works in more details.
What is useState:
So useState is a hook which helps you to handle state in a functional component.
How is it working?
Once you call useState you need to pass the initial value of the state what you would like to use in your functional component. It returns a pair of values the count and setCount.
So let's have your example below:
const [count, setCount] = useState(0);
So useState returned two items where count is the current value. And the second item, setCount is a function which can be used to update the value of the count state.
count can be used to represent the state for example the value in a div element:
return (
<div>{count}</div>
)
In order to update the value you can achieve by calling setState(12).
From the docs you can read further here.

According to the React official website:
React keeps track of the currently rendering component. Thanks to the Rules of Hooks, we know that Hooks are only called from React components (or custom Hooks — which are also only called from React components).
There is an internal list of “memory cells” associated with each component. They’re just JavaScript objects where we can put some data. When you call a Hook like useState(), it reads the current cell (or initializes it during the first render), and then moves the pointer to the next one. This is how multiple useState() calls each get independent local state.
Reference:
How does React associate Hook calls with components?

Why doesn't useState function initialize State every time?
I think you're confused with:
const [count, setCount] = useState(0);
As it's just a variable!?!
Yes, it's just a variable but it will take everytime the function runs from the useState hook. And it is the local state like you have seen in class based component.

Related

Status tracking and props in hooks - How does React keeps (track) state and props in Hooks?

I know that in React class components React uses the "this" binding to "track" props and state. In hooks it is achieved thanks to closures, is my doubt?
function Counter() {
const [count, setCount] = useState(0);
return (
<div>
<p>You clicked {count} times</p>
<button onClick={() => setCount(count + 1)}>
Click me
</button>
</div>
);
}
This code works as you would expect a counter, if you were using class component you would have to use setState() in callback mode to access the previous state, but in hooks how does the magic happen?
are there any bindings on the hooks or not?
React keeps track of state by internally counting the number of times useState is called the first time a component mounts. The value passed into useState is then set into React's internal state. For example, given
const Component = () => {
const [state1, setState1] = useState('one');
const [state2, setState2] = useState('two');
return 'foo';
};
React will then have the following state stored internally:
['one', 'two']
with one item in the (hidden, internal) state array for each call of useState that there is.
When a state setter is called, the corresponding item in the internal state array will be updated, and then the component will re-render. When a component re-renders, each useState call then returns the appropriate item in the internal state array. The first useState call will return the first item in the internal state array, the second useState call will return the second item, and so on.
In your code, with hooks, the click handler has a closure over the value of count that existed at that particular render of Counter.
if you were using class component you would have to use setState() in callback mode to access the previous state
Not really - if this code was a class component, it would be free to reference this.state.count directly without using the callback version.

Why setState causes too many rerender Error even though the state hasn't changed

Hi I'm learning React now and having trouble with the state..
I know when the state changes, the component re-renders and the code in UseEffect widout depth only runs once.
But I can't explain exactly why infinite rendering occurs when I write setState in JSX or in the render syntax.
below code causes infinite re-render
import React, { useState, useEffect } from 'react'
const index = () => {
const [active, setActive] = useState(false);
console.log("render", active);
setActive(false);
return (
<div>
</div>
)
}
export default index
But the code below has no problem even though it keeps calling setState.
import React, { useState, useEffect } from 'react'
const index = () => {
const [active, setActive] = useState(false);
console.log("render", active);
useEffect(() => {
setInterval(()=>{
console.log("run")
setActive(true)
},0);
}, [])
return (
<div>
</div>
)
}
Does setState trigger re-rendering regardless of state value?
I want to know the exact reason why using setState outside of useEffect causes an error.
This is happening because, in the first case, when useEffect is not used,
you are updating your state right after declaring it.
Even if you are setting the state as false again, but for react, the state has been updated. And the first rule of thumb for react is, if state update happens, component will re render.
This is why you are getting an infinite rerendering.
your code is following the below flow:
Declare state variable and pass value as false
Update state to false
State updated, hence component re rendered.
Step 1 again.
In second case, where use effect is used, your state will update only when the component is mounted, which means, after that any state update won't trigger your useEffect.
Based on React documentation: https://reactjs.org/docs/hooks-reference.html#usestate
The setState function is used to update the state. It accepts a new state value and enqueues a re-render of the component.
And there is an addition: https://reactjs.org/docs/hooks-reference.html#bailing-out-of-a-state-update
If you update a State Hook to the same value as the current state, React will bail out without rendering the children or firing effects. (React uses the Object.is comparison algorithm.) Note that React may still need to render that specific component again before bailing out.
And here is the important part: React may still need to render that specific component again before bailing out.
So yes, the component may still rerender even if the values are the same.

How does useState hook know the calling context in react

I am switching from using class components into using functional components in React. I read through their documentation and I like to know how the useState hook work.
In their FAQ they the same question that I'm asking, by saying that each component have a internal list: for storing the state variables, and that the useState know the calling component for storing the state variable.
I want to know how does useState know the calling component since we don't pass it anything other than the initial state value.
Can someone explain me this with a example? I really want to know how this work.
In short, at the begining of render a component, React generate a value like currentComponentContext. When you call useState, React will bind this state with currentComponentContext.
see function mountState and dispatchAction in ReactFiberHooks.new.js, react bind the state with currentlyRenderingFiber.
useState is the state hook provided by react. It returns a “pair” the current state value and a function to update it and also takes a single argument which is the initial value that you want to assign for the state variable.
In the above example count is the state variable and setCount is the function for changing the value and 0 is the default value we are assigning to count. In this example we used a counter as integer value just for demonstration, but we can use any other type like string, object, array etc also we can use multiple state variables defined in a single component.
import React, { useState } from 'react;
const MyComponent = (props) => {
const [count, setCount] = useState(0)
return (
<div>
<p>Count: {count}</p>
<button onClick={() => setCount(count + 1)}>
Increment Count
</button>
<button onClick={() => setCount(count - 1)}>
Decrement Count
</button>
</div>
)
}
export const MyComponent;
Assuming that seterInClass is an arrow function define to set the value of the variable username.
setterInClass = (val) =>{
this.setState({username:val});
}
in a class the initialization is through this.state
in a functional it is through the userState which acts as a glue.
this.state = {username:''} + setterInClass is equivalent to const [username, setUsername] = useState('').
Meaning useState is establishing a relation of setter to the variable username, after initializing it; And avoid us to write this.state to get the value of any variable or having top write const {username} = this.state;
So it is cleaner, less code for us and make functionals component looks cute
"useState" returns an array with two items. In the first index you have the state itself and in the second index you will get a function to handle that state.
Do this and you will understand :
const useStateArray = useState();
console.log(useStateArray[0]);
console.log(useStateArray[1]);

Purpose of React state

This might be a really stupid question but I am writing my first project in React and am struggling to understand the purpose of setState hooks.
As far as I understand, the setState hook is used to set current values used in a component that is scoped to that component only, and does not persist if a page is reloaded for example, the value is simply held in memory until it is destroyed.
My question is, what is the difference between using setState() to store values and just simply declaring a let variable and updating it the regular way? Both methods just seem to be holding a non-persisting value scoped to that component. What is the difference?
changes in the state automatically cause your app to re-render (in most cases), so typically you store data in a state that is being displayed and possibly changed throughout the app (a menu whose options can change based on previous selections, for example).
TL;DR, even though the answer's not very long:
setState or useState is the key for React to subscribe to your component's state and update your components when necessary. Using let variables for storing app state means React will never get to know about state change and won't rerender and update your components.
A short overview of React
The core principle of React is that your components, and consequentially your UI, are a function of your app's state. When your app's state changes, components "react" to this state change and get updated. Here's a simple example:
const CounterButton = () => {
// Create a state variable for counting number of clicks
const [count, setCount] = React.useState(0);
// Decide what the component looks like, as a function of this state
return (
<button onClick={() => setCount(count + 1)}>
Count: {count}
</button>
);
};
ReactDOM.render(<CounterButton />, document.querySelector('#root'));
<div id="root"></div>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.8.4/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.8.4/umd/react-dom.production.min.js"></script>
This is a component that just creates a button that shows how many times it has been clicked. Now, the component needs to store information about how many times it has been clicked - this means that the clicks count is a part of this component's "state". That's what we get from React.useState(0) - a state variable whose initial value is 0, and a function that allows us to change the value. Whenever you call setCount with some value, React gets to know that the CounterButton component's state has changed and thus the CounterButton component needs a rerender.
So in other words, React allows you to neatly and concisely define what internal state a component requires and what the component looks like as a function of this internal state (and external props). React does rest of the work - it manages the app's state, and whenever a piece of state changes anywhere in the app, React updates the components that depend on that. In other words, components "react" to data change.
To your question
If you use a simple let variable instead of React.useState in the above example, React will no longer get to know if the count variable has changed. useState is the key for React to "subscribe" to your component's state.
const CounterButton = () => {
// React will never get to know about this variable
let count = 0;
return (
<button onClick={() => count++}>
Count: {count}
</button>
);
};
In fact, for a functional component, let variables won't work in any case because while rendering a functional component, React internally runs the function. That would mean your let variable would be reset to its default value. The above reason is more relevant to class components. Using let variables to store component state is like hiding things from React - and that's not good because then there's no one else to rerender your component when component state changes :)
This part of the React docs is a bit relevant - it does not go into any details, though.
React re-renders the new / updated state on an event occurance storing value into a variable wont trigger re-render and data is passed on form parent component to child component through props and a change in state can be reflected among all the parts.
For example we need to print 100 elements on a page if an element is modified or updated in any way this triggers re-render but using var if the variable is modified or updated this won't cause re-render where in data wont be updated.

Can I declare a variable outside of useEffect ? React Hooks

I'm learning React Hooks, and I'm actually using the useEffect method.
No problem at all, but I got some warnings about my variable declarations.
Here's an example of what I wrote :
import React, { useRef, useEffect } from 'react';
function App(){
let containerRef = useRef(null);
let myVariable;
useEffect(){
myVariable = containerRef.children[0];
}
return(
<div className="container" ref={el => containerRef = el}>
<h1>Hey, I'm Laurie </h1>
<p> Nice to e-meet you!</p>
</div>
)
}
This is just an easy and uncompleted example of what I did, for animating my website with GSAP. I access to the DOM elements with useRef and I only found this solution.
But my console write me some warnings, and I'm pretty lost.
Warning I got :
Assignments to the myVariable variable from inside React Hook useEffect will be lost after each render. To preserve the value over time, store it in a useRef Hook and keep the mutable value in the '.current' property. Otherwise, you can move this variable directly inside useEffect.
Can someone help me with this issue ?
when you are using Hook basically you are telling React that your component needs to do something after render. React will remember the function you passed, and call it later after performing the DOM updates.
More Details
https://reactjs.org/docs/hooks-effect.html#example-using-hooks
Regarding warning: React doesn't remember your myVariable. It will be recreated on each render. It will be better to use useState hook to set value in useEffect and remember it on the next render.
Remember one thing always pass the second argument in useEffect with an array of dependencies.

Categories

Resources