क्या आप सेटस्टैट पर कॉल किए बिना रेंडर करने के लिए एक रिएक्ट घटक को बाध्य कर सकते हैं?


690

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

शीर्ष-स्तर के साथ React.renderयह संभव हो गया है, लेकिन एक घटक के भीतर यह काम नहीं करता है (जो कि कुछ समझ में आता है क्योंकि renderविधि सिर्फ एक वस्तु लौटाती है)।

यहाँ एक कोड उदाहरण है:

export default class MyComponent extends React.Component {

  handleButtonClick() {
    this.render();
  }

  render() {
    return (
      <div>
        {Math.random()}
        <button onClick={this.handleButtonClick.bind(this)}>
          Click me
        </button>
      </div>
    )
  }
}

बटन पर क्लिक करने से आंतरिक रूप से कॉल होता है this.render(), लेकिन यह वास्तव में प्रतिपादन होने का कारण नहीं बनता है (आप इसे कार्रवाई में देख सकते हैं क्योंकि पाठ द्वारा बनाया गया पाठ {Math.random()}बदलता है)। हालांकि, अगर मैं this.setState()इसके बजाय बस फोन this.render()करता हूं, तो यह ठीक काम करता है।

इसलिए मुझे लगता है कि मेरा सवाल यह है: क्या रिएक्टर के घटकों को रेंडर करने के लिए राज्य की आवश्यकता है? क्या राज्य को बदलने के बिना घटक को मांग पर अद्यतन करने के लिए मजबूर करने का एक तरीका है?


7
स्वीकार किए जाते हैं जवाब कहते हैं this.forceUpdate()सही समाधान है, जबकि सभी उत्तर और कई टिप्पणियां के बाकी का उपयोग कर के खिलाफ हैं forceUpdate()। क्या तब यह कहना ठीक होगा कि प्रश्न का उचित समाधान / उत्तर अभी तक नहीं मिला है?
आदि

6
उस समय मेरे प्रश्न का उत्तर दिया गया था। क्या तकनीकी रूप से वह उत्तर है जिसकी मुझे तलाश थी, और मुझे अभी भी सही उत्तर लगता है। मुझे लगता है कि अन्य उत्तर एक ही सवाल के साथ लोगों के लिए अच्छी पूरक जानकारी है।
फिलिप वाल्टन

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

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

जवाबों:


765

अपने घटक में, आप this.forceUpdate()एक रेंडरर को मजबूर करने के लिए कॉल कर सकते हैं ।

प्रलेखन: https://facebook.github.io/react/docs/component-api.html


169
एक और तरीका यह है ।सेटस्टैट (यह .स्टेट);
कर

25
बल प्रयोग को हतोत्साहित किया जाता है, कृपया अंतिम उत्तर देखें।
वारंड पीज़ेशियन

42
हालांकि this.forceUpdate(), यह पूछने वालों की समस्या का बहुत अच्छा समाधान नहीं है, यह शीर्षक में प्रस्तुत प्रश्न का सही उत्तर है। जबकि इसे आमतौर पर टाला जाना चाहिए, ऐसे हालात हैं जब बलप्रयोग एक अच्छा उपाय है।
अरनेहुगो

8
@kar वास्तव में, shouldComponentUpdate()आपके समाधान को निरर्थक बताने के लिए अतिरिक्त तर्क को लागू किया जा सकता है ।
क्वर्टी

4
अधिकतम कॉल स्टैक का आकार पार हो गया
IntoTheDeep

326

forceUpdateबचना चाहिए क्योंकि यह एक प्रतिक्रिया मानसिकता से भटकता है। प्रतिक्रिया डॉक्स का उदाहरण दिया forceUpdateजाता है कि इसका उपयोग कब किया जा सकता है:

डिफ़ॉल्ट रूप से, जब आपके घटक की स्थिति या प्रॉप्स बदलते हैं, तो आपका घटक फिर से प्रस्तुत करेगा। हालाँकि, यदि ये परिवर्तन स्पष्ट रूप से होते हैं (उदाहरण के लिए: वस्तु के भीतर गहरा डेटा वस्तु को बदले बिना बदल जाता है) या यदि आपकी रेंडर () विधि कुछ अन्य डेटा पर निर्भर करती है, तो आप रिएक्ट को बता सकते हैं कि उसे कॉल करके रेंडर () को फिर से चलाने की आवश्यकता है बलपूर्वक जानकारी()।

हालाँकि, मैं इस विचार को प्रस्तावित करना चाहूंगा कि गहरी नेस्टेड वस्तुओं के साथ भी, forceUpdateअनावश्यक है। एक अपरिवर्तनीय डेटा स्रोत का उपयोग करके ट्रैकिंग परिवर्तन सस्ते हो जाते हैं; एक परिवर्तन हमेशा एक नई वस्तु में परिणाम होगा, इसलिए हमें केवल यह जांचना होगा कि वस्तु का संदर्भ बदल गया है या नहीं। आप अपने एप्लिकेशन में अपरिवर्तनीय डेटा ऑब्जेक्ट्स को कार्यान्वित करने के लिए लाइब्रेरी Immutable JS का उपयोग कर सकते हैं ।

आम तौर पर आपको बलप्रयोग () के सभी उपयोगों से बचने की कोशिश करनी चाहिए और केवल इस से पढ़ा जाना चाहिए। यह और रेंडर में यह। ()। यह आपके घटक को "शुद्ध" और आपके आवेदन को बहुत सरल और अधिक कुशल बनाता है। बलपूर्वक जानकारी()

जिस तत्व को आप फिर से प्रस्तुत करना चाहते हैं उसकी कुंजी को बदलना काम करेगा। राज्य के माध्यम से अपने तत्व पर कुंजी प्रोप सेट करें और फिर जब आप नई कुंजी के लिए सेट स्थिति को अपडेट करना चाहते हैं।

<Element key={this.state.key} /> 

तब एक परिवर्तन होता है और आप कुंजी को रीसेट करते हैं

this.setState({ key: Math.random() });

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

जबकि ओपी के सवाल का सही जवाब होगा कि forceUpdate()मुझे यह समाधान विभिन्न स्थितियों में मददगार लगा। मैं यह भी नोट करना चाहता हूं कि यदि आप स्वयं का उपयोग कर पाते हैं तो आप forceUpdateअपने कोड की समीक्षा कर सकते हैं और देख सकते हैं कि क्या कोई और तरीका है।

नोट 1-9-2019:

उपरोक्त (कुंजी को बदलना) तत्व को पूरी तरह से बदल देगा। यदि आप पाते हैं कि बदलाव करने के लिए आप खुद को अपडेट कर रहे हैं तो आपके कोड में कहीं और समस्या है। Math.random()कुंजी का उपयोग करके प्रत्येक रेंडर के साथ तत्व को फिर से बनाया जाएगा। मैं इस तरह से कुंजी को अपडेट करने की सिफारिश नहीं करूंगा क्योंकि प्रतिक्रिया चीजों को फिर से प्रस्तुत करने का सबसे अच्छा तरीका निर्धारित करने के लिए कुंजी का उपयोग करती है।


16
मुझे यह जानने में दिलचस्पी होगी कि यह गिरावट क्यों हुई? मैं अपने सिर को पीट रहा हूँ स्क्रीन पाठकों को पाने के लिए aria अलर्ट का जवाब देने की कोशिश कर रहा हूं और यह एकमात्र तकनीक है जो मैंने पाया है कि मज़बूती से काम करता है। यदि आपके यूआई में कुछ ऐसा है जो हर बार क्लिक होने पर उसी अलर्ट को उत्पन्न करता है, तो डिफ़ॉल्ट प्रतिक्रिया द्वारा DOM को फिर से प्रस्तुत नहीं करता है इसलिए स्क्रीन रीडर परिवर्तन की घोषणा नहीं करता है। एक अद्वितीय कुंजी सेट करना यह काम करता है। शायद डाउनवोट इसलिए था क्योंकि इसमें अभी भी राज्य स्थापित करना शामिल है। लेकिन कुंजी सेट करके DOM को फिर से रेंडर करने के लिए मजबूर करना सुनहरा है!
मार्टिन बेली

2
मुझे यह उत्तर बहुत पसंद आया क्योंकि - 1: फ़ोर्सअपडेट () का उपयोग हतोत्साहित किया जाता है, और 2: यह तरीका 3 पार्टी घटकों के लिए बहुत सहायक है जो आपने npm के माध्यम से स्थापित किया है, जिसका अर्थ है कि आपके स्वयं के घटक नहीं। उदाहरण के लिए रिएक्टिव-रिसाइवलिंग-एंड मूवेबल एक 3 पार्टी घटक है जिसका मैं उपयोग करता हूं, लेकिन यह मेरे घटक सेटस्टेट पर प्रतिक्रिया नहीं कर रहा है। यह बहुत अच्छा उपाय है।
वारंड पीज़ेशियन

81
यह एक हैक और एक दुरुपयोग है key। पहला, यह आशय स्पष्ट नहीं है। आपके कोड के एक पाठक को यह समझने के लिए कड़ी मेहनत करनी होगी कि आप keyइस तरह क्यों इस्तेमाल कर रहे हैं । दूसरा, यह इससे अधिक शुद्ध नहीं है forceUpdate। "शुद्ध" प्रतिक्रिया का मतलब है कि आपके घटक की दृश्य प्रस्तुति इसके राज्य पर 100% निर्भर है, इसलिए यदि आप किसी भी राज्य को बदलते हैं, तो यह अपडेट होता है। यदि फिर भी, आपके पास कुछ गहरी नेस्टेड ऑब्जेक्ट हैं (परिदृश्य forceUpdateडॉक्स इसका उपयोग करने के लिए एक कारण का हवाला forceUpdateदेता है ) तो इसका उपयोग स्पष्ट करता है। तीसरा, Math.random()है ... यादृच्छिक। सैद्धांतिक रूप से, यह एक ही यादृच्छिक संख्या उत्पन्न कर सकता है।
एटमकिर्क

8
@xtraSimplicity मैं इस बात से सहमत नहीं हो सकता कि यह चीजों को करने के रिएक्ट तरीके का अनुपालन करता है। forceUpdateऐसा करने का रिएक्ट तरीका है।
रोब ग्रांट

3
@ रॉबर्ट ग्रांट, पीछे मुड़कर देखता हूं, मैं सहमत हूं। जोड़ा जटिलता वास्तव में इसके लायक नहीं है।
XtraSimplicity

80

वास्तव में, forceUpdate()एकमात्र सही समाधान है क्योंकि यदि अतिरिक्त तर्क को लागू किया जाता है या जब यह केवल रिटर्न करता है, तो पुन: रेंडर को ट्रिगर नहीं किया setState()जा सकता है ।shouldComponentUpdate()false

बलपूर्वक जानकारी()

कॉलिंग forceUpdate()को render()कंपोनेंट पर बुलाया जाएगा, लंघन किया जाएगा shouldComponentUpdate()अधिक...

setState ()

setState()जब तक सशर्त प्रतिपादन तर्क लागू नहीं किया जाता है तब तक हमेशा एक पुन: रेंडर को ट्रिगर करेगा shouldComponentUpdate()अधिक...


forceUpdate() द्वारा अपने घटक के भीतर से बुलाया जा सकता है this.forceUpdate()


हुक: मैं कैसे रिएक्ट में हुक के साथ फिर से प्रस्तुत करने के लिए घटक को मजबूर कर सकता हूं?


BTW: क्या आप राज्य को बदल रहे हैं या आपके नेस्टेड गुण प्रचार नहीं करते हैं?


1
एक दिलचस्प बात यह है कि इस तरह के सेटस्टेट के बाहर राज्य assingments.state.foo = 'बार' रेंडर जीवन चक्र विधि को ट्रिगर नहीं करेगा
lfender6445

4
@ lfender6445 कंस्ट्रक्टर के this.stateबाहर के साथ सीधे स्टेट असाइन करना भी एक त्रुटि फेंकना चाहिए। 2016 में ऐसा नहीं किया जा सकता है; लेकिन, मुझे पूरा यकीन है कि यह अब ऐसा करता है।
टायलर

मैंने प्रत्यक्ष राज्य असाइनमेंट के आसपास काम करने के लिए कुछ लिंक जोड़े हैं।
क्वर्टी

36

मैंने फॉलो करने forceUpdateसे परहेज किया

गलत तरीके : कुंजी के रूप में सूचकांक का उपयोग न करें

this.state.rows.map((item, index) =>
   <MyComponent cell={item} key={index} />
)

सही तरीका : डेटा आईडी को कुंजी के रूप में उपयोग करें, यह कुछ गाइड आदि हो सकता है

this.state.rows.map((item) =>
   <MyComponent item={item} key={item.id} />
)

इसलिए इस तरह के कोड में सुधार करने से आपका घटक अद्वितीय होगा और स्वाभाविक रूप से प्रस्तुत होगा


this.state.rows.map((item) => <MyComponent item={item} key={item.id} /> )
ताल

मुझे सही दिशा में लाने के लिए बहुत-बहुत धन्यवाद। कुंजी के रूप में सूचकांक का उपयोग करना वास्तव में मेरी समस्या थी।
रोइक्स

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

34

जब आप संवाद करने के लिए दो रिएक्ट घटक चाहते हैं, जो एक रिश्ते (माता-पिता-बच्चे) से बाध्य नहीं हैं, तो फ्लक्स या इसी तरह के आर्किटेक्चर का उपयोग करना उचित है ।

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

आम तौर पर आपको उपयोग करने से बचने की कोशिश करनी चाहिए forceUpdate()। प्रलेखन से:

आम तौर पर आपको बलप्रयोग () के सभी उपयोगों से बचने की कोशिश करनी चाहिए और केवल इस से पढ़ा जाना चाहिए। यह और रेंडर में यह। ()। यह आपके एप्लिकेशन को बहुत सरल और अधिक कुशल बनाता है


2
एक घटक राज्य की मेमोरी स्थिति क्या है? यदि मेरे पास एक पृष्ठ पर पांच घटक हैं और वे सभी एक ही दुकान पर सुन रहे हैं, तो क्या मेरे पास स्मृति में पांच बार डेटा है, या वे संदर्भ हैं? और उन सभी श्रोताओं का उपवास नहीं है? अपने लक्ष्य को डेटा पास करने की तुलना में "ट्रिकल डाउन" करना बेहतर क्यों है?
एजेफर्कास

5
दरअसल सिफारिशें स्टोर डेटा को कंपोनेंट प्रॉप्स में पास करने के लिए होती हैं और केवल स्क्रॉल स्टेट और अन्य छोटी यूआई-विशिष्ट चीजों जैसी चीजों के लिए कंपोनेंट स्टेट का उपयोग किया जाता है। यदि आप रिडक्स का उपयोग करते हैं (मैं इसे सुझाता हूं), तो आप कनेक्ट होने वाले फ़ंक्शन का उपयोग react-reduxस्वचालित रूप से स्टोर स्थिति से घटक प्रॉपर में मैप करने के लिए कर सकते हैं जब भी आप एक मैपिंग फ़ंक्शन के आधार पर आपूर्ति करते हैं।
स्टिजेन डे विट

1
@AJFarkas राज्य को एक स्टोर के डेटा को सौंपा जाएगा जो कि इसके लिए एक संकेतक है, वैसे भी मेमोरी कोई समस्या नहीं है जब तक कि आप क्लोनिंग नहीं कर रहे हैं।
जेसन सेब्रिंग

4
"forceUpdate () से हमेशा बचना चाहिए" गलत है। प्रलेखन स्पष्ट रूप से कहता है: "आम तौर पर आपको बलप्रयोग ()" के सभी उपयोगों से बचने की कोशिश करनी चाहिए। वहाँ के मान्य उपयोग के मामले हैंforceUpdate
AJP

2
@AJP आप बिलकुल सही कह रहे हैं, वह व्यक्तिगत पूर्वाग्रह था :) मैंने जवाब संपादित किया है।
गिडो

18

हुक या HOC का उपयोग करें

हुक या एचओसी (उच्चतर ऑर्डर कंपोनेंट) पैटर्न का उपयोग करते हुए , आपके स्टोर बदलने पर आपके पास स्वचालित अपडेट हो सकते हैं। यह एक फ्रेमवर्क के बिना बहुत हल्का वजन दृष्टिकोण है।

स्टोर अपडेट्स को संभालने के लिए यूज़स्ट्रस्ट हूक तरीका

interface ISimpleStore {
  on: (ev: string, fn: () => void) => void;
  off: (ev: string, fn: () => void) => void;
}

export default function useStore<T extends ISimpleStore>(store: T) {
  const [storeState, setStoreState] = useState({store});
  useEffect(() => {
    const onChange = () => {
      setStoreState({store});
    }
    store.on('change', onChange);
    return () => {
      store.off('change', onChange);
    }
  }, []);
  return storeState.store;
}

withStores HOC स्टोर अपडेट को संभालता है

export default function (...stores: SimpleStore[]) {
  return function (WrappedComponent: React.ComponentType<any>) {
    return class WithStore extends PureComponent<{}, {lastUpdated: number}> {
      constructor(props: React.ComponentProps<any>) {
        super(props);
        this.state = {
          lastUpdated: Date.now(),
        };
        this.stores = stores;
      }

      private stores?: SimpleStore[];

      private onChange = () => {
        this.setState({lastUpdated: Date.now()});
      };

      componentDidMount = () => {
        this.stores &&
          this.stores.forEach((store) => {
            // each store has a common change event to subscribe to
            store.on('change', this.onChange);
          });
      };

      componentWillUnmount = () => {
        this.stores &&
          this.stores.forEach((store) => {
            store.off('change', this.onChange);
          });
      };

      render() {
        return (
          <WrappedComponent
            lastUpdated={this.state.lastUpdated}
            {...this.props}
          />
        );
      }
    };
  };
}

सिंपलस्टोर क्लास

import AsyncStorage from '@react-native-community/async-storage';
import ee, {Emitter} from 'event-emitter';

interface SimpleStoreArgs {
  key?: string;
  defaultState?: {[key: string]: any};
}

export default class SimpleStore {
  constructor({key, defaultState}: SimpleStoreArgs) {
    if (key) {
      this.key = key;
      // hydrate here if you want w/ localState or AsyncStorage
    }
    if (defaultState) {
      this._state = {...defaultState, loaded: false};
    } else {
      this._state = {loaded: true};
    }
  }
  protected key: string = '';
  protected _state: {[key: string]: any} = {};
  protected eventEmitter: Emitter = ee({});
  public setState(newState: {[key: string]: any}) {
    this._state = {...this._state, ...newState};
    this.eventEmitter.emit('change');
    if (this.key) {
      // store on client w/ localState or AsyncStorage
    }
  }
  public get state() {
    return this._state;
  }
  public on(ev: string, fn:() => void) {
    this.eventEmitter.on(ev, fn);
  }
  public off(ev: string, fn:() => void) {
    this.eventEmitter.off(ev, fn);
  }
  public get loaded(): boolean {
    return !!this._state.loaded;
  }
}

कैसे इस्तेमाल करे

हुक के मामले में:

// use inside function like so
const someState = useStore(myStore);
someState.myProp = 'something';

HOC के मामले में:

// inside your code get/set your store and stuff just updates
const val = myStore.myProp;
myOtherStore.myProp = 'something';
// return your wrapped component like so
export default withStores(myStore)(MyComponent);

यह सुनिश्चित करें कि वैश्विक परिवर्तन का लाभ पाने के लिए एक सिंगलटन के रूप में अपने स्टोर का निर्यात करें:

class MyStore extends SimpleStore {
  public get someProp() {
    return this._state.someProp || '';
  }
  public set someProp(value: string) {
    this.setState({...this._state, someProp: value});
  }
}
// this is a singleton
const myStore = new MyStore();
export {myStore};

यह दृष्टिकोण बहुत सरल है और मेरे लिए काम करता है। मैं बड़ी टीमों में भी काम करता हूं और Redux और MobX का उपयोग करता हूं और उन लोगों को भी अच्छा लगता हूं लेकिन बहुत सारे बॉयलरप्लेट। मैं व्यक्तिगत रूप से अपने स्वयं के दृष्टिकोण को पसंद करता हूं क्योंकि मुझे हमेशा किसी ऐसी चीज के लिए बहुत सारे कोड से नफरत थी, जो तब सरल हो सकती है जब आपको इसकी आवश्यकता हो।


2
मुझे लगता है कि अद्यतन विधि में आपके स्टोर वर्ग के उदाहरण में एक टाइपो है, जिसमें निम्न विधि की पहली पंक्ति लिखनी है this._data = {...this._data, ...newData}:।
नोर्बर्ट

2
प्रतिक्रिया रचना के पक्ष में विरासत को हतोत्साहित करती है। reactjs.org/docs/composition-vs-inheritance.html
फ्रेड

1
बस स्पष्टता / पठनीयता के बारे में सोचकर, इस.सेटस्टैट (it.state) को इस से बेहतर कैसे माना जाए ।forceUpdate ()?
ज़ोमन

17

इसलिए मुझे लगता है कि मेरा सवाल यह है: क्या रिएक्टर के घटकों को रेंडर करने के लिए राज्य की आवश्यकता है? क्या राज्य को बदलने के बिना घटक को मांग पर अद्यतन करने के लिए मजबूर करने का एक तरीका है?

अन्य उत्तरों ने यह बताने की कोशिश की है कि आप कैसे हो सकते हैं, लेकिन मुद्दा यह है कि आपको ऐसा नहीं करना चाहिए । यहां तक ​​कि कुंजी को बदलने का हैकी समाधान बिंदु को याद करता है। रिएक्ट की शक्ति मैन्युअल रूप से प्रबंधित करने का नियंत्रण दे रही है जब कुछ को प्रस्तुत करना चाहिए, और इसके बजाय बस अपने आप को इनपुट पर कुछ मैप करना चाहिए। फिर इनपुट की धारा की आपूर्ति।

यदि आपको मैन्युअल रूप से फिर से प्रस्तुत करने की आवश्यकता है, तो आप निश्चित रूप से कुछ सही नहीं कर रहे हैं।


@ कला-सोलोपोव, आप किस समस्या का उल्लेख कर रहे हैं? कौन से डॉक्स उन्हें पेश करते हैं? और यह मानते हुए कि आप राज्य में नेस्टेड ऑब्जेक्ट्स का उल्लेख कर रहे हैं, इसका उत्तर आपके राज्य को संग्रहीत करने के लिए एक अलग संरचना का उपयोग करना है। यह स्पष्ट रूप से प्रतिक्रिया में राज्य को संभालने का एक उप-इष्टतम तरीका है। आपको अलग से राज्य का प्रबंधन भी नहीं करना चाहिए। यदि आप राज्य-प्रबंधन प्रणाली के साथ काम नहीं करते हैं तो आप रिएक्ट का सबसे बड़ा लाभ खो रहे हैं । अपडेट को मैन्युअल रूप से प्रबंधित करना एक एंटी-पैटर्न है।
काइल बेकर

कृपया, क्या आप इस प्रश्न को जांच सकते हैं stackoverflow.com/questions/61277292/… ?
हुलु वीका

4

आप इसे कुछ तरीके से कर सकते हैं:

1. forceUpdate()विधि का प्रयोग करें :

forceUpdate()विधि का उपयोग करते समय कुछ गड़बड़ियां हो सकती हैं । एक उदाहरण यह है कि यह shouldComponentUpdate()विधि को नजरअंदाज करता है और इस बात पर ध्यान दिए बिना कि क्या shouldComponentUpdate()झूठा रिटर्न देता है। इसके कारण जब संभव हो तो बलप्रयोग () का उपयोग करने से बचना चाहिए।

2. इस setState()विधि से गुजरना

कोड की निम्न पंक्ति पिछले उदाहरण के साथ समस्या पर काबू पाती है:

this.setState(this.state);

वास्तव में यह सब कुछ वर्तमान स्थिति के साथ वर्तमान स्थिति को अधिलेखित कर रहा है जो पुन: प्रतिपादन को ट्रिगर करता है। यह आवश्यक रूप से चीजों को करने का सबसे अच्छा तरीका नहीं है, लेकिन यह कुछ ग्लिट्स को पार कर सकता है जिन्हें आप बलप्रयोग () विधि का उपयोग करके सामना कर सकते हैं।


2
चूँकि सेटस्टैट को बैचेन किया गया है, इसलिए यह शायद सुरक्षित है:this.setState(prevState => prevState);
मार्क गैलोवे

1
वास्तव में यकीन नहीं है कि क्यों एक 'गड़बड़' है। विधि का नाम ('forceUpdate') स्पष्ट नहीं हो सका: हमेशा अद्यतन को बाध्य करें।
ज़ोमन

4

आपके घटक को पुन: प्रस्तुत करने के कुछ तरीके हैं:

सबसे सरल उपाय बलप्रयोग () विधि का उपयोग करना है:

this.forceUpdate()

एक और उपाय यह है कि राज्य में उपयोग की जाने वाली कुंजी (nonUsedKey) न बनाएं और इस nonUsedKey के अपडेट के साथ setState फ़ंक्शन को कॉल करें:

this.setState({ nonUsedKey: Date.now() } );

या सभी वर्तमान स्थिति को फिर से लिखना:

this.setState(this.state);

प्रॉप्स बदलने से कंपोनेंट रेंडरर भी मिलता है।


3

पूर्णता के लिए, आप इसे कार्यात्मक घटकों में भी प्राप्त कर सकते हैं:

const [, updateState] = useState();
const forceUpdate = useCallback(() => updateState({}), []);
// ...
forceUpdate();

या, पुन: प्रयोज्य हुक के रूप में:

const useForceUpdate = () => {
  const [, updateState] = useState();
  return useCallback(() => updateState({}), []);
}
// const forceUpdate = useForceUpdate();

देखें: https://stackoverflow.com/a/53215514/2692307

कृपया ध्यान दें कि बल-अद्यतन तंत्र का उपयोग करना अभी भी बुरा व्यवहार है क्योंकि यह प्रतिक्रिया मानसिकता के खिलाफ जाता है, इसलिए यदि संभव हो तो इसे अभी भी टाला जाना चाहिए।


2

हम नीचे के रूप में इस .forceUpate () का उपयोग कर सकते हैं।

       class MyComponent extends React.Component {



      handleButtonClick = ()=>{
          this.forceUpdate();
     }


 render() {

   return (
     <div>
      {Math.random()}
        <button  onClick={this.handleButtonClick}>
        Click me
        </button>
     </div>
    )
  }
}

 ReactDOM.render(<MyComponent /> , mountNode);

DOM में तत्व 'Math.random' केवल तब भी अपडेट होता है जब आप घटक को फिर से प्रस्तुत करने के लिए setState का उपयोग करते हैं।

यहाँ सभी उत्तर सही समझ के लिए प्रश्न को पूरक कर रहे हैं..जैसे हम जानते हैं कि एक घटक को फिर से प्रस्तुत करना है जिसमें से सेटस्टैट ({}) का उपयोग करके किया जाता है बलप्रयोग () का उपयोग करके।

उपरोक्त कोड नीचे के रूप में सेटस्टेट के साथ चलता है।

 class MyComponent extends React.Component {



             handleButtonClick = ()=>{
                this.setState({ });
              }


        render() {
         return (
  <div>
    {Math.random()}
    <button  onClick={this.handleButtonClick}>
      Click me
    </button>
  </div>
)
  }
 }

ReactDOM.render(<MyComponent /> , mountNode);

1

स्वीकृत उत्तर का बैक अप लेने के लिए बस एक और उत्तर :-)

रिएक्ट के उपयोग को हतोत्साहित करता है forceUpdate()क्योंकि उनके पास आमतौर पर एक बहुत ही "ऐसा करने का एकमात्र तरीका है" कार्यात्मक प्रोग्रामिंग की ओर रुख करता है। यह कई मामलों में ठीक है, लेकिन कई रिएक्ट डेवलपर्स एक ओओ-पृष्ठभूमि के साथ आते हैं, और उस दृष्टिकोण के साथ, एक ऑब्जर्वेबल ऑब्जेक्ट को सुनने के लिए पूरी तरह से ठीक है।

और यदि आप करते हैं, तो आप शायद यह जानते हैं कि जब अवलोकन योग्य "आग" होती है, तो आपको फिर से प्रस्तुत करना होगा, और इसलिए, आप उपयोग करना चाहिए forceUpdate()और यह वास्तव में एक प्लस हैshouldComponentUpdate() यहां शामिल नहीं है।

MobX जैसे उपकरण, जो एक OO-दृष्टिकोण लेता है, वास्तव में सतह के नीचे यह कर रहा है (वास्तव में MobX कॉल render()सीधे)


0

मैंने जबरदस्ती से बचना सबसे अच्छा पाया है ()। री-रेंडर करने के लिए मजबूर करने का एक तरीका अस्थायी बाहरी चर पर रेंडर की निर्भरता को जोड़ना (और जब भी जरूरत हो, उस वैरिएबल के मूल्य को बदलना है।

यहाँ एक कोड उदाहरण है:

class Example extends Component{
   constructor(props){
      this.state = {temp:0};

      this.forceChange = this.forceChange.bind(this);
   }

   forceChange(){
      this.setState(prevState => ({
          temp: prevState.temp++
      })); 
   }

   render(){
      return(
         <div>{this.state.temp &&
             <div>
                  ... add code here ...
             </div>}
         </div>
      )
   }
}

जब आप पुन: रेंडर करने के लिए मजबूर करना चाहते हैं, तो इस .force () को कॉल करें।


0

ES6 - मैं एक उदाहरण सहित हूं, जो मेरे लिए उपयोगी था:

"लघु यदि कथन" में आप इस तरह से खाली फ़ंक्शन पास कर सकते हैं:

isReady ? ()=>{} : onClick

यह सबसे छोटा तरीका है।

()=>{}



0

एक और तरीका है setState, और राज्य को संरक्षित करना:

this.setState(prevState=>({...prevState}));


0

forceUpdate (), लेकिन हर बार जब भी मैंने कभी किसी को इसके बारे में बात करते सुना है, तो इसका अनुसरण किया गया है, आपको कभी भी इसका उपयोग नहीं करना चाहिए।


-1

आप अधिक विवरण जांच ( forceUpdate () ) के लिए forceUpdate () का उपयोग कर सकते हैं ।


1
जिज्ञासा से बाहर, इस उत्तर को क्यों छोड़ दें यदि 4 साल से लोगों ने पहले से ही इस धागे में एक संभावित समाधान के रूप में पेश किया है?
बायरन कोएत्सी
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.