ReactJS: अधिकतम अद्यतन गहराई त्रुटि से अधिक हो गई


178

मैं ReactJS में एक घटक के राज्य टॉगल करने के लिए कोशिश कर रहा हूँ, लेकिन मैं यह कहते हुए कोई त्रुटि मिलती है:

अधिकतम अद्यतन गहराई पार हो गई। यह तब हो सकता है जब कोई घटक बार-बार कॉल करता है। सीमा प्रतिक्रिया नेस्ट अपडेट की संख्या अनंत लूप को रोकने के लिए।

मुझे अपने कोड में अनंत लूप नहीं दिख रहा है, क्या कोई मदद कर सकता है?

ReactJS घटक कोड:

import React, { Component } from 'react';
import styled from 'styled-components';

class Item extends React.Component {
    constructor(props) {
        super(props);     
        this.toggle= this.toggle.bind(this);
        this.state = {
            details: false
        } 
    }  
    toggle(){
        const currentState = this.state.details;
        this.setState({ details: !currentState }); 
    }

    render() {
        return (
            <tr className="Item"> 
                <td>{this.props.config.server}</td>      
                <td>{this.props.config.verbose}</td> 
                <td>{this.props.config.type}</td>
                <td className={this.state.details ? "visible" : "hidden"}>PLACEHOLDER MORE INFO</td>
                {<td><span onClick={this.toggle()}>Details</span></td>}
            </tr>
    )}
}

export default Item;

35
बदलें this.toggle()करने के लिए this.toggleया{()=> this.toggle()}
शिक्षार्थी

8
एक और सुधार, हालांकि आपकी समस्या से संबंधित नहीं: बारी toggle(){...}में toggle = () => {...}तो आप की जरूरत नहीं है bindयह!
बेरी एम।

थैंक्स @ लर्नर। आपने मेरी मदद भी की। आप कृपया अपने समाधान के पीछे कारण की व्याख्या करता है। उन दोनों में क्या अंतर है?
शमीम

2
@Shamim यह एक मौजूदा कार्यप्रणाली को कॉल, और एक समारोह के संदर्भ में गुजर के बीच का अंतर है। यह समझना महत्वपूर्ण है कि हम लिख रहे हैं कोड प्रदर्शित होता है और शुरू हो रहा है जब उपयोगकर्ता कुछ करता है, नहीं कोड के रूप में जल्द उपयोगकर्ता लोड होने पर पेज शुरू किया जा करने के लिए किया जा करने के लिए उपयोगी है। reactjs.org/docs/faq-functions.html
DisplayName

जवाबों:


274

क्योंकि आप रेंडर करने की विधि के अंदर टॉगल कॉल कर रहे हैं, जो री-रेंडर करने का कारण बनेगा और टॉगल फिर से कॉल करेगा और री-रेंडरिंग और फिर से

अपने कोड में इस लाइन

{<td><span onClick={this.toggle()}>Details</span></td>}

आप के लिए बनाने की जरूरत onClickका उल्लेख this.toggleयह बुला नहीं

समस्या को ठीक करने के लिए ऐसा करें

{<td><span onClick={this.toggle}>Details</span></td>}

8
मैं एक समान स्थिति का सामना कर रहा हूं, लेकिन मुझे टॉगल करने के लिए एक पैरामीटर पास करने की आवश्यकता है, यह कैसे पूरा किया जा सकता है?
निवेदिता कर्मेगम

58
@ निवेदिताकर्मागेम दो onClick={(param) => this.toggle(param)}। यह तुरंत (और रेंडरर) आग नहीं देगा। यह एक कॉलबैक परिभाषा (एरो फंक्शन) है।
फैबियन Picone

15
@FabianPicone अपने विधि की कोशिश की लेकिन जब मैं console.log यह पता चलता है कि "param" घटना के रूप में पारित किया गया था, वास्तव में क्या करना चाहिएonClick={() => this.toggle(param)}
iWillGetBetter

6
@iWillGetBetter हाँ पर क्लिक करने वाला पहला पर क्लिक इवेंट है। यदि आपको अतिरिक्त पैराम की आवश्यकता है तो आप इसे भी पास कर सकते हैं onClick={(event) => this.toggle(event, myParam)}
फैबियन Picone

1
मेरे पास यह फ़ंक्शन है closeEditModal = () => this.setState({openEditModal: false});कि इसे रेंडर में कैसे कॉल करें?
नक्स

31

जब समारोह बुला आप घटना वस्तु पारित करना चाहिए:

{<td><span onClick={(e) => this.toggle(e)}>Details</span></td>}

यदि आपको ऑनक्लिक इवेंट को संभालने की आवश्यकता नहीं है, तो आप भी टाइप कर सकते हैं:

{<td><span onClick={(e) => this.toggle()}>Details</span></td>}

अब आप फ़ंक्शन के भीतर अपने पैरामीटर भी जोड़ सकते हैं।


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

2
{<td><span onClick={() => this.toggle(whateverParameter)}>Details</span></td>}करता है मेरे लिए चाल
iWillGetBetter

22

पहले प्रतिक्रिया के बारे में भूल जाओ:
यह प्रतिक्रिया से संबंधित नहीं है और हमें जावा स्क्रिप्ट की बुनियादी अवधारणाओं को समझने दें। उदाहरण के लिए आपने java script में निम्नलिखित फ़ंक्शन को लिखा है (नाम A है)।

function a() {

};

Q.1) जिस फ़ंक्शन को हमने परिभाषित किया है, उसे कैसे कॉल करें?
उत्तर: ए ();

Q.2) फ़ंक्शन का संदर्भ कैसे पारित करें ताकि हम इसे बाद में कह सकें?
उत्तर: मौज = ए;

अब आप अपने प्रश्न के लिए आ रहा है, तो आप समारोह नाम के साथ paranthesis का इस्तेमाल किया है, इसका मतलब यह है कि समारोह कॉल किया जाएगा निम्न कथन प्रस्तुत करना हो जाएगा।

<td><span onClick={this.toggle()}>Details</span></td>

फिर इसे सही कैसे करें?
सरल!! बस कोष्ठक हटा दें। इस तरह से आपने उस फ़ंक्शन का संदर्भ ऑनक्लिक इवेंट में दिया है। यह आपके फ़ंक्शन को तभी कॉल करेगा जब आपका घटक क्लिक किया जाएगा।

 <td><span onClick={this.toggle}>Details</span></td>

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

{<td><span onClick={(e) => this.toggle(e)}>Details</span></td>}

https://cdb.reacttraining.com/react-inline-functions-and-performance-bdff784f5578


6

मुझे पता है कि इसके बहुत सारे उत्तर हैं, लेकिन उनमें से ज्यादातर पुराने हैं (अच्छी तरह से, पुराने), कोई भी दृष्टिकोण का उल्लेख नहीं कर रहा है मैं वास्तव में जल्दी के लिए बढ़ता हूं। संक्षेप में:

कार्यात्मक घटकों और हुक का उपयोग करें

अब में:

बहुत कार्यात्मक घटकों के बजाय वर्ग वाले के रूप में उपयोग करने का प्रयास विशेष रूप से प्रतिपादन के लिए , और उन्हें (हाँ, डेटा डिफ़ॉल्ट रूप से गंदा है मुझे पता है) संभव के रूप में शुद्ध रूप में रखने का प्रयास करें।

कार्यात्मक घटकों के दो स्पष्ट रूप से स्पष्ट लाभ (अधिक हैं):

  • शुद्धता या निकटता, डिबगिंग को इतना आसान बना देती है
  • कार्यात्मक घटक निर्माता बायलर कोड की आवश्यकता को दूर करते हैं

2 अंक के लिए त्वरित प्रमाण - क्या यह बिल्कुल घृणित नहीं है?

constructor(props) {
        super(props);     
        this.toggle= this.toggle.bind(this);
        this.state = {
            details: false
        } 
    }  

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

इस मामले में आपको केवल दो हुक चाहिए:

एक कॉलबैक हुक नाम आसानी से useCallback। इस तरह से आप बार-बार रेंडर करने पर फंक्शन को रोक रहे हैं।

एक राज्य हुक, जिसे useStateपूरे घटक के कार्य करने और अपनी संपूर्णता में निष्पादित करने के बावजूद राज्य रखने के लिए कहा जाता है (हाँ, यह हुक के जादू के कारण संभव है)। उस हुक के भीतर आप टॉगल के मूल्य को संग्रहीत करेंगे।

यदि आप इस हिस्से को पढ़ते हैं, तो आप शायद यह देख सकते हैं कि मैंने सभी कार्रवाई के बारे में बात की है और मूल समस्या पर लागू किया है। यहां आप जाएं: डेमो

उन लोगों के लिए जो केवल घटक को देखना चाहते हैं और डब्ल्यूटीएफ इस बारे में है, यहां आप हैं:

const Item = () => {

    // HOOKZ
  const [isVisible, setIsVisible] = React.useState('hidden');

  const toggle = React.useCallback(() => {
    setIsVisible(isVisible === 'visible' ? 'hidden': 'visible');
  }, [isVisible, setIsVisible]);

    // RENDER
  return (
  <React.Fragment>
    <div style={{visibility: isVisible}}>
        PLACEHOLDER MORE INFO
    </div>
    <button onClick={toggle}>Details</button>
  </React.Fragment>
  )
};

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


5

यदि आपको कार्य करने के लिए तर्कों को पास करने की आवश्यकता नहीं है, तो नीचे दिए गए फ़ंक्शन से निकालें ():

<td><span onClick={this.toggle}>Details</span></td>

लेकिन अगर आप तर्क पारित करना चाहते हैं, तो आपको नीचे की तरह करना चाहिए:

<td><span onClick={(e) => this.toggle(e,arg1,arg2)}>Details</span></td>

3

ReactJS: अधिकतम अद्यतन गहराई त्रुटि से अधिक हो गई

inputDigit(digit){
  this.setState({
    displayValue: String(digit)
  })

<button type="button"onClick={this.inputDigit(0)}>

यह क्यों?

<button type="button"onClick={() => this.inputDigit(1)}>1</button>

फ़ंक्शन onDigit राज्य को सेट करता है, जो कि एक रेंडरर का कारण बनता है, जो onDigit को आग का कारण बनता है क्योंकि वह मूल्य जो आप onClick पर सेट कर रहे हैं, जो राज्य को सेट करने का कारण बनता है, जो कि एक रेंडरर का कारण बनता है, जो onDigit को आग लगाने का कारण बनता है क्योंकि यह वह मूल्य है जो ' पुनः ... आदि


3

1.अगर हम कॉल में तर्क पारित करना चाहते हैं तो हमें नीचे दिए गए तरीके से कॉल करने की आवश्यकता है क्योंकि हम एरो फ़ंक्शंस का उपयोग कर रहे हैं ताकि विधि को बाध्य करने की आवश्यकता न हो cunstructor

onClick={() => this.save(id)} 

जब हम इस तरह से कंस्ट्रक्टर में विधि बांधते हैं

this.save= this.save.bind(this);

फिर हमें नीचे दिए गए किसी भी तर्क को पारित किए बिना विधि को कॉल करने की आवश्यकता है

onClick={this.save}

और हम फ़ंक्शन को कॉल करते समय तर्क पास करने की कोशिश करते हैं जैसा कि नीचे दिखाया गया है, फिर त्रुटि आती है जैसे अधिकतम गहराई पार हो गई।

 onClick={this.save(id)}

1

onClick आपको फ़ंक्शन को कॉल करना चाहिए, thats ने आपके फ़ंक्शन को टॉगल कहा है।

onClick={() => this.toggle()}


1

इस मामले में, यह कोड

{<td><span onClick={this.toggle()}>Details</span></td>}

फ़ंक्शन को तुरंत कॉल करने का कारण बनता है और इसे फिर से रेंडर करता है और इस प्रकार अनंत कॉल करता है।

तो केवल उस टॉगल विधि के संदर्भ को पारित करने से समस्या हल हो जाएगी।

इसलिए ,

{<td><span onClick={this.toggle}>Details</span></td>}

समाधान कोड होगा।

यदि आप () का उपयोग करना चाहते हैं, तो आपको इस तरह से एक तीर फ़ंक्शन का उपयोग करना चाहिए

{<td><span onClick={()=> this.toggle()}>Details</span></td>}

यदि आप पैरामीटर को पास करना चाहते हैं तो आपको अंतिम विकल्प चुनना चाहिए और आप इस तरह से पैरामीटर पारित कर सकते हैं

{<td><span onClick={(arg)=>this.toggle(arg)}>Details</span></td>}

अंतिम स्थिति में यह तुरंत कॉल नहीं करता है और फ़ंक्शन को फिर से प्रस्तुत करने का कारण नहीं बनता है, इसलिए अनंत कॉल से बचना चाहिए।

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