← Back to React Course | Chapter 4: State & Event Handling | Lesson 9 of 10

Functional State Updates करना

एक functional update React को बताता है 'जो भी value currently है उसे लो और वहां से change करो' इसके बजाय कि यह guess किया जाए कि यह अभी क्या हो सकती है।
Syntax
markup
setState((previous) => newValueBasedOn(previous));

setCount((prev) => prev + 1);

Stale Values की Problem

जब आप same function में एक direct value जैसे setCount(count + 1) उपयोग करते हुए एक state setter को multiple बार call करते हैं, हर call उस render से capture की गई SAME count value use करती है -- वे वैसे stack up नहीं होतीं जैसे आप expect कर सकते हैं।

यह updates को silently lost होने का कारण बन सकता है।

Note: अगर आप कभी एक row में same setter को एक से ज़्यादा बार previous value के आधार पर call करें, यह एक sign है कि आपको functional form चाहिए।
Warning: setCount(count + 1) को एक row में दो बार call करना सिर्फ total 1 से increment करता है, 2 से नहीं, क्योंकि दोनों calls same stale count देखती हैं।

उदाहरण: The Problem with Stale Values

markup
<!DOCTYPE html>
<html>
<head>
  <script src="https://unpkg.com/react@18/umd/react.development.js"></script>
  <script src="https://unpkg.com/react-dom@18/umd/react-dom.development.js"></script>
  <script src="https://unpkg.com/@babel/standalone/babel.min.js"></script>
</head>
<body>
  <div id="root"></div>
  <script type="text/babel">
    function BuggyCounter() {
      const [count, setCount] = React.useState(0);
      function handleClick() {
        setCount(count + 1);
        setCount(count + 1); // Still uses the same stale count -- only +1 total!
      }
      return <button onClick={handleClick}>{count}</button>;
    }
    ReactDOM.createRoot(document.getElementById('root')).render(<BuggyCounter />);
  </script>
</body>
</html>

Functional Update Form Use करना

Setter को एक direct value के बजाय एक function pass करना React को आपको truly latest state value एक argument के रूप में देने देता है, even same handler में multiple calls भर में। हर call correctly पिछले वाले के result पर build करती है।

Note: Convention function के parameter को prev (short for 'previous value') नाम देना है, जैसे setCount(prev => prev + 1)।
Warning: Same handler में functional और direct updates mix करना अब भी confusion का कारण बन सकता है -- doubt होने पर functional form consistently prefer करें।

उदाहरण: Using the Functional Update Form

markup
<!DOCTYPE html>
<html>
<head>
  <script src="https://unpkg.com/react@18/umd/react.development.js"></script>
  <script src="https://unpkg.com/react-dom@18/umd/react-dom.development.js"></script>
  <script src="https://unpkg.com/@babel/standalone/babel.min.js"></script>
</head>
<body>
  <div id="root"></div>
  <script type="text/babel">
    function FixedCounter() {
      const [count, setCount] = React.useState(0);
      function handleClick() {
        setCount(prev => prev + 1);
        setCount(prev => prev + 1); // Correctly adds +2 total
      }
      return <button onClick={handleClick}>{count}</button>;
    }
    ReactDOM.createRoot(document.getElementById('root')).render(<FixedCounter />);
  </script>
</body>
</html>

Timers और Callbacks के अंदर Functional Updates

Functional update form खासतौर पर setTimeout, event listeners, या दूसरे callbacks के अंदर important है जो कुछ delay के बाद run हो सकते हैं -- उस point तक, एक directly-captured state variable outdated हो सकता है।

Functional form हमेशा current value पाता है जब यह actually run होता है।

Note: setTimeout, setInterval, या एक Promise .then() के अंदर कोई भी state update functional update form के लिए एक strong candidate है।
Warning: एक delayed callback के अंदर एक stale, directly-captured value उपयोग करना React bugs का एक बहुत common source है।

उदाहरण: Functional Updates Inside Timers and Callbacks

markup
<!DOCTYPE html>
<html>
<head>
  <script src="https://unpkg.com/react@18/umd/react.development.js"></script>
  <script src="https://unpkg.com/react-dom@18/umd/react-dom.development.js"></script>
  <script src="https://unpkg.com/@babel/standalone/babel.min.js"></script>
</head>
<body>
  <div id="root"></div>
  <script type="text/babel">
    function DelayedIncrement() {
      const [count, setCount] = React.useState(0);
      function incrementLater() {
        setTimeout(() => setCount(prev => prev + 1), 500);
      }
      return <button onClick={incrementLater}>Count: {count}</button>;
    }
    ReactDOM.createRoot(document.getElementById('root')).render(<DelayedIncrement />);
  </script>
</body>
</html>
Related Topics
{# common_mistakes/chapter_summary/browser_support: on Hindi pages the view already swaps in the hi_ translation fields (or blanks these out if untranslated), so this renders correctly for both languages without a lang_code check here. #}
आम गलतियां
  1. Previous value के आधार पर state को row में multiple बार update करते समय direct value form (setCount(count + 1)) उपयोग करना।
  2. यह मान लेना कि functional form सिर्फ counters के लिए चाहिए -- यह किसी भी state update पर apply होता है जो previous value पर depend करता है।
  3. यह भूल जाना कि updater function LATEST state अपने argument के रूप में receive करता है, necessarily handler defined होने के समय की value नहीं।
चैप्टर सारांश
  • एक state setter का functional form एक direct value के बजाय एक function लेता है।
  • वह function सबसे up-to-date previous state को इसके argument के रूप में receive करता है।
  • यह state को row में multiple बार या closures के अंदर update करने का safe तरीका है।
  • यह एक earlier render से एक stale value reference करने से होने वाले bugs से बचाता है।
ब्राउज़र सपोर्ट

कोई browser-specific restrictions नहीं -- useState/useReducer के लिए available है जब से Hooks React 16.8 में introduce हुए थे।

Login to run this code

C/C++/Java/PHP execution requires a free account. Your code is saved — you'll land right back in the editor after logging in.