setState राज्य को तुरंत अपडेट नहीं करता है


103

मैं पूछना चाहता हूं कि जब मैं ऑनक्लिक ईवेंट करता हूं तो मेरा राज्य क्यों नहीं बदल रहा है। मैंने कुछ समय पहले खोजा है कि मुझे कंस्ट्रक्टर में ऑनक्लिक फ़ंक्शन को बांधने की आवश्यकता है लेकिन फिर भी राज्य अपडेट नहीं कर रहा है। यहाँ मेरा कोड है:

import React from 'react';

import Grid from 'react-bootstrap/lib/Grid';
import Row from 'react-bootstrap/lib/Row';
import Col from 'react-bootstrap/lib/Col';

import BoardAddModal from 'components/board/BoardAddModal.jsx';

import style from 'styles/boarditem.css';

class BoardAdd extends React.Component {

    constructor(props){
        super(props);

        this.state = {
            boardAddModalShow: false
        }

        this.openAddBoardModal = this.openAddBoardModal.bind(this);
    }
    openAddBoardModal(){
        this.setState({ boardAddModalShow: true });
// After setting a new state it still return a false value
        console.log(this.state.boardAddModalShow);

    }

    render() {

        return (
            <Col lg={3}>
                <a href="javascript:;" className={style.boardItemAdd} onClick={this.openAddBoardModal}>
                    <div className={[style.boardItemContainer,style.boardItemGray].join(' ')}>
                        Create New Board
                    </div>
                </a>



            </Col>
        )
    }
}

export default BoardAdd

5
इस प्रश्न पर आपके द्वारा स्वीकार किए गए उत्तर का कोई मतलब नहीं है। setStateएक वादा वापस नहीं करता है। यदि यह काम करता है, तो यह केवल इसलिए काम करता है क्योंकि awaitफ़ंक्शन में एक async "टिक" का परिचय देता है, और यह हुआ कि उस टिक के दौरान राज्य अद्यतन संसाधित हो गया। इसकी गारंटी नहीं है। जैसा कि यह उत्तर कहता है, आपको पूर्ण कॉलबैक का उपयोग करने की आवश्यकता है (यदि आपको राज्य के अद्यतन होने के बाद वास्तव में कुछ करने की आवश्यकता है, जो असामान्य है। आम तौर पर, आप बस फिर से प्रस्तुत करना चाहते हैं, जो स्वचालित रूप से हैपन करता है)।
टीजे क्राउडर

यह अच्छा होगा यदि आप वर्तमान में स्वीकार किए गए उत्तर को स्वीकार नहीं करते हैं या एक सही स्वीकार करते हैं, क्योंकि यह तब कई सवालों के लिए एक डुप्लिकेट के रूप में इस्तेमाल किया जा सकता है। शीर्ष पर गलत उत्तर देना भ्रामक है।
गाइ इनकॉगनिटो

जवाबों:


12

यह कॉलबैक वास्तव में गड़बड़ है। इसके बजाय async प्रतीक्षा का उपयोग करें:

async openAddBoardModal(){
    await this.setState({ boardAddModalShow: true });
    console.log(this.state.boardAddModalShow);
}

24
इसका कोई अर्थ नही बन रहा है। रिएक्ट setStateएक वादा वापस नहीं करता है।
टीजे क्राउडर

16
@TJCrowder सही है। setStateएक वादा वापस नहीं करता है, इसलिए यह इंतजार नहीं किया जाना चाहिए। उस ने कहा, मुझे लगता है कि मैं देख सकता हूं कि यह कुछ लोगों के लिए क्यों काम कर रहा है, क्योंकि वेट कॉल के स्टैक पर सेटस्टैट के अंदरूनी कामकाज को बाकी फ़ंक्शन के आगे रखता है, इसलिए यह पहले संसाधित हो जाता है, और इस तरह लगता है जैसे राज्य हो गया है सेट। यदि setState में कोई नई एसिंक्रोनस कॉल होती या लागू होती, तो यह उत्तर विफल हो जाता। इस फ़ंक्शन को ठीक से लागू करने के लिए, आप इसका उपयोग कर सकते हैं:await new Promise(resolve => this.setState({ boardAddModalShow: true }, () => resolve()))
माइक रिचर्ड्स

कैसे async this.setState({})मेरी समस्या हल हो गई? हमारे पास वर्किंग कोड था, कुछ और विकास किया गया है लेकिन ऐप के उस हिस्से में कुछ भी नहीं बदला है। सेटस्टेट में केवल दो ऑब्जेक्ट्स में से एक को अपडेट किया जा रहा था, जिससे यह एसिंक्स वापस कार्यक्षमता वापस आ गया और अब दोनों ऑब्जेक्ट सही ढंग से अपडेट हो रहे हैं। मुझे कुछ पता नहीं है कि क्या गलत था।
Ond Sepej Ševčík

145

आपके राज्य को म्यूट करने के लिए कुछ समय चाहिए, और चूंकि console.log(this.state.boardAddModalShow)स्टेट म्यूटेट्स से पहले निष्पादित होता है, इसलिए आपको आउटपुट के रूप में पिछला मान मिलता है। तो आपको कॉलबैक में setStateफ़ंक्शन को कंसोल लिखने की आवश्यकता है

openAddBoardModal() {
  this.setState({ boardAddModalShow: true }, function () {
    console.log(this.state.boardAddModalShow);
  });
}

setStateअतुल्यकालिक है। इसका मतलब है कि आप इसे एक पंक्ति में नहीं बुला सकते हैं और मान सकते हैं कि राज्य अगले पर बदल गया है।

React डॉक्स के अनुसार

setState()तुरंत उत्परिवर्तन नहीं करता है, this.stateलेकिन एक लंबित राज्य संक्रमण बनाता है। this.stateइस पद्धति को कॉल करने के बाद एक्सेस करना मौजूदा मूल्य को संभावित रूप से वापस कर सकता है। कॉल सेट करने के लिए सिंक्रोनस ऑपरेशन की कोई गारंटी नहीं है और प्रदर्शन लाभ के लिए कॉल को बैच किया जा सकता है।

वे setStateasync क्यों करेंगे?

ऐसा इसलिए है क्योंकि setStateराज्य को बदल देता है और पुनर्जन्म का कारण बनता है। यह एक महंगा ऑपरेशन हो सकता है और इसे तुल्यकालिक बनाने से ब्राउज़र अप्रतिसादी हो सकता है।

इस प्रकार setStateकॉल अतुल्यकालिक हैं और साथ ही बेहतर यूआई अनुभव और प्रदर्शन के लिए बैचेन हैं।


अब तक यह एक महान विचार है, लेकिन क्या होगा यदि हम कंसोल का उपयोग नहीं कर सकते हैं। क्योंकि आप एस्लिंट नियमों का उपयोग कर रहे हैं?
मौदेव

2
@maudev, eslint नियम आपको कंसोल.लॉग के लिए रोकते हैं ताकि वे उत्पादन में समाप्त न हों, लेकिन उपरोक्त उदाहरण पूरी तरह से डिबगिंग के लिए है। और कंसोल.लॉग और एक कार्रवाई के साथ प्रतिस्थापित किया जाए जो अद्यतन स्थिति को ध्यान में रखता है
शुभम खत्री

1
क्या होगा अगर कॉलबैक आपके कहे अनुसार काम नहीं करता है? मेरा नहीं है!
एलेक्स जोलीग

33

सौभाग्य setState() से एक कॉलबैक लेता है। और यह वह जगह है जहाँ हम अद्यतन स्थिति प्राप्त करते हैं।

इस उदाहरण पर विचार करें।

this.setState({ name: "myname" }, () => {                              
        //callback
        console.log(this.state.name) // myname
      });

तो जब कॉलबैक फायर करता है, तो यह अपडेटेड स्थिति है।
आप mutated/updatedकॉलबैक में डेटा प्राप्त कर सकते हैं ।


1
आप इस कॉलबैक का उपयोग किसी भी फंक्शन को पास करने के लिए भी कर सकते हैं initMap(), उदाहरण के लिए
Dende

जाने के लिए रास्ता! अंत में मेरी समस्या हल हो गई। बहुत बहुत धन्यवाद।
अहमत हलिलोविक

11

चूंकि सेटसेट एक अतुल्यकालिक फ़ंक्शन है, इसलिए आपको इस तरह से कॉलबैक के रूप में राज्य को कंसोल करना होगा।

openAddBoardModal(){
    this.setState({ boardAddModalShow: true }, () => {
        console.log(this.state.boardAddModalShow)
    });
}

6

setState()हमेशा घटक को तुरंत अपडेट नहीं करता है। यह बाद में अपडेट को बैच या स्थगित कर सकता है। यह setState()एक संभावित नुकसान को बुलावा देने के तुरंत बाद इसे पढ़ता है । इसके बजाय, उपयोग componentDidUpdateया setStateकॉलबैक ( setState(updater, callback)), जिनमें से किसी को अपडेट लागू होने के बाद आग लगने की गारंटी है। यदि आपको पिछली स्थिति के आधार पर राज्य को सेट करने की आवश्यकता है, तो नीचे updater तर्क के बारे में पढ़ें।

setState()जब तक shouldComponentUpdate()झूठे वापस नहीं आएंगे, तब तक फिर से रेंडर हो जाएगा । यदि उत्परिवर्तनीय वस्तुओं का उपयोग किया जा रहा है और सशर्त रेंडरिंग लॉजिक को लागू नहीं किया जा सकता है shouldComponentUpdate(), तो setState()केवल तभी कॉल करना जब नया राज्य पिछले राज्य से भिन्न होता है, अनावश्यक पुन: रेंडरर्स से बचता है।

पहला तर्क हस्ताक्षर के साथ एक updater फ़ंक्शन है:

(state, props) => stateChange

stateपरिवर्तन लागू होने के समय घटक स्थिति का संदर्भ है। इसे सीधे म्यूट नहीं किया जाना चाहिए। इसके बजाय, राज्य और प्रॉप्स से इनपुट के आधार पर एक नई वस्तु का निर्माण करके परिवर्तनों का प्रतिनिधित्व किया जाना चाहिए। उदाहरण के लिए, मान लीजिए कि हम प्रॉप्स द्वारा राज्य में मूल्य बढ़ाना चाहते थे।

this.setState((state, props) => {
    return {counter: state.counter + props.step};
});

2

यदि आप अपडेट करना चाहते हैं कि राज्य अपडेट हो रहा है या नहीं, तो वही काम करने का दूसरा तरीका है

_stateUpdated(){
  console.log(this.state. boardAddModalShow);
}

openAddBoardModal(){
  this.setState(
    {boardAddModalShow: true}, 
    this._stateUpdated.bind(this)
  );
}

हर बार जब आप डिबगिंग के लिए स्थिति को अपडेट करने का प्रयास करते हैं तो आप "_stateUpdated" विधि को कॉल कर सकते हैं।


1

setState()अतुल्यकालिक है। यह सत्यापित करने का सबसे अच्छा तरीका है कि राज्य अपडेट कर रहा है componentDidUpdate()या नहीं और console.log(this.state.boardAddModalShow)बाद में रखा जाएगा this.setState({ boardAddModalShow: true })

रिएक्ट डॉक्स के अनुसार

घटक को अद्यतन करने के लिए तत्काल आदेश के बजाय सेटस्टैट () के बारे में सोचें। बेहतर प्रदर्शन के लिए, प्रतिक्रिया में देरी हो सकती है, और फिर एक पास में कई घटकों को अपडेट कर सकते हैं। प्रतिक्रिया की गारंटी नहीं है कि राज्य परिवर्तन तुरंत लागू होते हैं


1

रिएक्ट डॉक्स के अनुसार

प्रतिक्रिया की गारंटी नहीं है कि राज्य परिवर्तन तुरंत लागू होते हैं। यह सेटस्टैट () को संभावित रूप से कॉल करने के बाद इसे पढ़ता है। pitfallयह संभवत: प्रकृति के existingकारण मूल्य को वापस कर सकता asyncहै। इसके बजाय, सेटस्टैट ऑपरेशन के ठीक बाद निष्पादित किए गए कॉलबैक componentDidUpdateया setStateकॉलबैक का उपयोग सफल होता है। आमतौर पर हम componentDidUpdate()इसके बजाय ऐसे तर्क के लिए उपयोग करने की सलाह देते हैं ।

उदाहरण:

import React from "react";
import ReactDOM from "react-dom";

import "./styles.css";

class App extends React.Component {
  constructor() {
    super();
    this.state = {
      counter: 1
    };
  }
  componentDidUpdate() {
    console.log("componentDidUpdate fired");
    console.log("STATE", this.state);
  }

  updateState = () => {
    this.setState(
      (state, props) => {
        return { counter: state.counter + 1 };
      });
  };
  render() {
    return (
      <div className="App">
        <h1>Hello CodeSandbox</h1>
        <h2>Start editing to see some magic happen!</h2>
        <button onClick={this.updateState}>Update State</button>
      </div>
    );
  }
}

const rootElement = document.getElementById("root");
ReactDOM.render(<App />, rootElement);


0

हुक के साथ ऐसा करने की कोशिश करने वाले किसी भी व्यक्ति के लिए, आपको आवश्यकता है useEffect

function App() {
  const [x, setX] = useState(5)
  const [y, setY] = useState(15) 

  console.log("Element is rendered:", x, y)

  // setting y does not trigger the effect
  // the second argument is an array of dependencies
  useEffect(() => console.log("re-render because x changed:", x), [x])

  function handleXClick() {
    console.log("x before setting:", x)
    setX(10)
    console.log("x in *line* after setting:", x)
  }

  return <>
    <div> x is {x}. </div>
    <button onClick={handleXClick}> set x to 10</button>
    <div> y is {y}. </div>
    <button onClick={() => setY(20)}> set y to 20</button>
  </>
}

आउटपुट:

Element is rendered: 5 15
re-render because x changed: 5
(press x button)
x before setting: 5
x in *line* after setting: 5
Element is rendered: 10 15
re-render because x changed: 10
(press y button)
Element is rendered: 10 20

-1

जब मैं कोड चला रहा था और अपने आउटपुट को कंसोल पर चेक कर रहा था, यह दिखा रहा था कि यह अपरिभाषित है। के बाद मैं चारों ओर खोज और कुछ है कि मेरे लिए काम किया लगता है।

componentDidUpdate(){}

मैंने इस विधि को कंस्ट्रक्टर () के बाद अपने कोड में जोड़ा। देशी वर्कफ़्लो के जीवन चक्र को देखें।

https://images.app.goo.gl/BVRAi4ea2P4LchqJ8


-2
 this.setState({
    isMonthFee: !this.state.isMonthFee,
  }, () => {
    console.log(this.state.isMonthFee);
  })

2
यह वही है जो सबसे अधिक उत्तर दिया गया उत्तर बताता है, लेकिन बिना किसी स्पष्टीकरण और 3 साल देर से। कृपया डुप्लिकेट उत्तर पोस्ट न करें जब तक कि आपके पास इसे जोड़ने के लिए कुछ प्रासंगिक न हो।
एमिल बर्जरोन

-2

हां क्योंकि setState एक अतुल्यकालिक फ़ंक्शन है। राज्य को लिखने के बाद सही तरीके से सेट करने का सबसे अच्छा तरीका ऑब्जेक्ट का उपयोग करना है। इस तरह से असाइन करें: उदाहरण के लिए आप एक संपत्ति सेट करना चाहते हैं। यह सच है, इसे इस तरह से करें


Object.assign (यह .स्टेट, {isValid: true})


आप इस पंक्ति को लिखने के बाद अद्यतन स्थिति तक पहुँच सकते हैं।


हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.