-1

In whichever site I visit to get my doubt clear about state in react I always found this defination in common which is: "an object of a set of observable properties that control the behavior of the component". And I still don't understand the state in react. Consider an example below

import React,{useState} from 'react';
export const City = ()=>{
    const [altitude,setAltitude] = useState("");
    const getAltitude=()=>{
        navigator.geolocation.watchPosition((position)=>{
            const alt = {
                lat:position.coords.latitude,
                long:position.coords.longitude
            }
            setAltitude(alt);
            console.log(altitude);
        })
    }   
    return(
        <div id="location">
        {getAltitude()} 
        <h3>This is location</h3>
        </div>
    )
}

But the above program can also be written without using state as shown below

import React,{useState} from 'react';

export const City = ()=>{
    let lat;
    let long;
    const getAltitude=()=>{
        navigator.geolocation.watchPosition((position)=>{
            lat = position.coords.latitude;
            long = position.coords.longitude;
        })
        console.log(lat,long);
    }
    
    return(
        <div id="location">
        {getAltitude()} 
        <h3>This is location</h3>
        </div>
    )

}

If we can write in this way too then what is the use of state in react. If I'm wrong I request you to explain me in detail. I'm not able to sleep unless this doubt doesn't get clear.

Shahriar
  • 1,855
  • 2
  • 21
  • 45
  • If you use regular variables, then your component won't re-render if/when those variables change. eg: if `watchPosition`'s callback is executed multiple times over a period of time, without using `setAltitude` your component will only ever render the initial JSX and won't render it with update values (note that state values are often used in the returned JSX which is rendered to the user, so you want your component to re-render when your variables/state changes) – Nick Parsons Jul 24 '21 at 10:34
  • Your examples add a new watch handler on every render and never clears them. You would wan't to register a single watch handler and have it update state in its success callback. You would also want to clear it on unmount. Look at useEffect and its interaction with useState. – pilchard Jul 24 '21 at 10:37

4 Answers4

1

For the understanding purpose I've created these two snippets, one using state variable and the other using regular js variables.

  1. Using state variable

const { useState } = React;

const Counter = () => {
  const [count, setCount] = useState(0);
  
  const onClick = () => {
    //Update the state
    setCount(c => c + 1);
  }
  
  return (
    <div>
      Count: {count}
      <div>
        <button onClick={onClick}>Increment</button>
      </div>
    </div>
  )
}

ReactDOM.render(<Counter />, document.getElementById("react"));
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.12.0/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.12.0/umd/react-dom.production.min.js"></script>

<div id="react"></div>
  1. Using regular variable

const { useState } = React;

const Counter = () => {
  let count = 0; 
  
  const onClick = () => {
    //Update the variable
    count += 1;
    console.log(count);
  }
  
  return (
    <div>
      Count: {count}
      <div>
        <button onClick={onClick}>Increment</button>
      </div>
    </div>
  )
}

ReactDOM.render(<Counter />, document.getElementById("react"));
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.12.0/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.12.0/umd/react-dom.production.min.js"></script>

<div id="react"></div>

In both of the above scenarios we are updating the count on click of the button, but then in scenario 1, the updated value is displayed on the DOM where as in scenario 2, it's not.

So, basically when you want to re-render the component on change of the variable we keep those variables in the state. React will be able to understand the state changes and update the DOM accordingly

Nithish
  • 5,393
  • 2
  • 9
  • 24
  • In addition to this nice explanation, I want to add one more detail to use `useState`. If regular js declaration is used, whenever something updates in component (for example a button click with onClick function), those regular js declarations will work again and again so then it can make memory leak in big components. – Mehmet Pekcan Jul 24 '21 at 11:06
  • Wow. such a nice explanation. I got it. – piyush shende Jul 24 '21 at 14:13
1

As stated correctly in your citation, React maintains a state that is used to to figure out, beside some other features, when to re-render your component. In your examples, it seems like you wanted to add an event listener for watchPosition, and show the calculated values in your City component. If I am correct please consider this example:

import React,{useState} from 'react';

export const City = ()=>{

    const [altitude,setAltitude] = useState({});

    const calculateAltitude=()=>{
        navigator.geolocation.watchPosition((position)=>{
            const alt = {
                lat:position.coords.latitude,
                long:position.coords.longitude
            }
            setAltitude(alt); // you set the state here
        })
    }   

    calculateAltitude(); // This function is called on each render. It's better to put it into a "componentDidMount" equivalent (second example)

    return(
        <div id="location">
        <h3>This is the location</h3>
        <div>Lat: {altitude.lat}</div> {/*You use the state here*/}
        <div>Lat: {altitude.long}</div>
        </div>
    )
}

Each time watchPosition is executed, your state altitude is updated and the component will re-render. This means, that the render function is executed and the current state of altitude is used to display the latitude and longitude. In the first example, calculateAltitude() will be executed each time, your component renders. Since that is not best practice, you should put that call into a useEffect hook, with an empty-array dependency. It is an equivalent to the componentDidMount() fucntion for React class components (React.Component). You can find a good explanation here.

So, in order to have a clean code, you should use this component:

import React,{useState, useEffect} from 'react';
export const City = ()=>{

  const [altitude,setAltitude] = useState({});

  const calculateAltitude=()=>{
    
    navigator.geolocation.watchPosition((position)=>{ // each time this geolocation lib calls your function, your state will be updated.
      const alt = {
        lat:position.coords.latitude,
        long:position.coords.longitude
      }
      setAltitude(alt); // you set the state here
    })
  }
  
  useEffect(() => 
  {
    calculateAltitude() // register your event listener once.
  },[]) // on Component mount. Executed once.
  

  return(
    <div id="location">
      <h3>This is the location</h3>
      <div>Lat: {altitude.lat}</div> {/*You use the state here. It is updated each time your geolocation lib calls your listener.*/}
      <div>Lat: {altitude.long}</div>
    </div>
  )
}

I recommend to read carefully about the React states. Here are some good links:

movcmpret
  • 179
  • 1
  • 10
0

One of the features that is at the fundament of React is that it allows you to update your UI, or, in other terms, the HTML output of your app, after a change to a variable. In React, state is a way to declare the variables that, depending on your business logic, can ultimately update the UI. React does this by keeping track of the state and rerendering parts of the HTML that need the update.

In your example, you made altitude part of your state, but your logic does not update the UI anywhere—it just determines a geolocation on first load. If this is what you want, that's fine, you won't need state for that. If, however, you want to make updates to your HTML, e.g. if you'd like to show the realtime location of a user on a map, you could make use of React's state: you write location updates to the state, and will need some custom logic that handles what happens if the altitude value has changed. You could write this custom logic as a side effect.

Cas Dekkers
  • 372
  • 2
  • 12
-2

state variables will be accessible into jsx ( i mean in rendered part of the component), so in your example, altitude will be accessible in the html part, but if you didn't assign it to state variable wont be able to access it

return(
        <div id="location">
        <h3>This is location {altitude.alt}</h3>
        </div>
    )
Mhd Wael Jazmati
  • 636
  • 9
  • 18