2016-12-19 16 views
5

से अधिक हो गया है मैं प्रतिक्रिया में काम कर रहा हूं और मूल रूप से मैं टूलटिप के साथ एक बटन बनाना चाहता हूं, अभी मैं टूलटिप बना रहा हूं। मैं सीएसएस डिस्प्ले प्रॉपर्टी को बदल रहा हूं ताकि माउस को दर्ज करने और छोड़ने के दौरान इसे दृश्यमान बनाया जा सके या नहीं। लेकिन वहाँ एक त्रुटि है और मैं क्या करना है पता नहीं है ...प्रतिक्रिया, अनकही रेंज त्रुटि: अधिकतम कॉल स्टैक आकार

यहाँ मेरी कोड है:

Uncaught RangeError: Maximum call stack size exceeded 
at defineRefPropWarningGetter (App.js:1053) 
at Object.ReactElement.createElement (App.js:1220) 
at Object.createElement (App.js:3329) 
at Constructor.render (App.js:43403) 
at App.js:15952 
at measureLifeCyclePerf (App.js:15233) 
at ReactCompositeComponentWrapper._renderValidatedComponentWithoutOwnerOrContext (App.js:15951) 
at ReactCompositeComponentWrapper._renderValidatedComponent (App.js:15978) 
at ReactCompositeComponentWrapper._updateRenderedComponent (App.js:15902) 
at ReactCompositeComponentWrapper._performComponentUpdate (App.js:15880) 

मैं:

import React from 'react'; 
import ReactDOM from 'react-dom'; 
import Style from 'style-it'; 
var Ink = require('react-ink'); 
import FontIcon from '../FontIcon/FontIcon'; 

var IconButton = React.createClass({ 

    getInitialState() { 
     return { 
      iconStyle: "", 
      style: "", 
      cursorPos: {}, 
     }; 
    }, 

    extend(obj, src) { 
     Object.keys(src).forEach(function(key) { obj[key] = src[key]; }); 
     return obj; 
    }, 

    Tooltip(props) { 

     var style = {}; 

     if (this.tooltipDisplay) { 
      style.display = "block"; 
     } else if (!this.tooltipDisplay) { 
      style.display = "none"; 
     }; 

     return <div className="tooltip" style={style}>{_props.tooltip}</div>; 
    }, 

    showTooltip(){ 
     this.tooltipDisplay = true; 
    }, 

    removeTooltip(){ 
     this.tooltipDisplay = false; 
    }, 

    render() { 

    var _props = this.props, 
     tooltip = this.Tooltip, 
     opts, 
     tooltipDisplay = false, 
     disabled = false, 
     rippleOpacity, 
     outterStyleMy = { 
     border: "none", 
      outline: "none", 
      padding: "8px 10px", 
     "background-color": "red", 
     "border-radius": 100 + "%", 
     cursor: "pointer", 
     }, 
     iconStyleMy = { 
      "font-size": 12 + "px", 
      "text-decoration": "none", 
      "text-align": "center", 
      display: 'flex', 
      'justify-content': 'center', 
      'align-items': 'center', 
     }, 
     rippleStyle = { 
     color: "rgba(0,0,0,0.5)", 
     }; 

    if (_props.disabled || _props.disableTouchRipple) { 
     rippleStyle.opacity = 0; 
    }; 

    this.setState({ 
     iconStyle: _props.iconStyle 
    }); 

    this.setState({ 
     style: _props.style 
    }); 

    if (_props.disabled) { 
     disabled = true; 
    }; 

    if (this.state.labelStyle) { 
     iconStyleMy = this.state.iconStyle; 
    }; 

    if (this.state.style) { 
     outterStyleMy = this.state.style; 
    }; 

    if (_props.href) { 
     opts.href = _props.href; 
    }; 

     var buttonStyle = this.extend(outterStyleMy, iconStyleMy); 

     return(
     <Style> 
     {` 
      .IconButton{ 
      position: relative; 
      } 
      .IconButton:disabled{ 
      color: ${_props.disabledColor}; 
      } 
      .btnhref{ 
      text-decoration: none; 
      } 
     `} 
     <a {...opts} className="btnhref" > 
      <tooltip text={this.props.tooltip} position={this.options} /> 
      <button ref="button" className={"IconButton" + _props.className} disabled={disabled} style={buttonStyle} 
      onMouseEnter={this.showTooltip} onMouseLeave={this.removeTooltip} > 
      <Ink background={true} style={rippleStyle} opacity={rippleOpacity} /> 
      <FontIcon className={_props.iconClassName}/> 
      </button> 
     </a> 
     </Style> 
     ); 

    } 
}); 



ReactDOM.render(
<IconButton href="" className="" iconStyle="" style="" iconClassName="face" disabled="" disableTouchRipple="" tooltip="aaaaa" />, 
document.getElementById('app') 
); 

कंसोल में मैं इस त्रुटि मिल रही है क्या गलत है पता नहीं कर सकता। मुझे पता है कि यह एक फ़ंक्शन को कॉल करने के बारे में कुछ हो सकता है जो बदले में एक और फ़ंक्शन कॉल करता है। लेकिन मैं अपने कोड में ऐसा कुछ नहीं देख सकता हूं और मुझे यकीन नहीं है कि यह सब कुछ है या नहीं। मदद :)

+8

कभी नहीं, कभी, किसी भी परिस्थिति में ... मुझे परवाह नहीं है क्या आप तर्क के लिए के लिए आ सकता है ... कभी अपने 'render' समारोह अंदर से' setState' कॉल नहीं करते ;) 'सेटस्टेट' को कॉल करने से पुनर्वितरण होता है, जो 'सेटस्टेट' को कॉल करने का कारण बनता है जो एक पुनर्विक्रय का कारण बनता है, जो तब 'सेटस्टेट' कहता है और इस प्रकार एक पुनर्वितरण का कारण बनता है, जो तब 'सेटस्टेट' को अभी तक agian कहते हैं, और आपके घटक को फिर से प्रस्तुत किया जाता है, फिर 'सेटस्टेट' को दोबारा बुलाया जाता है और दूसरा पुन: प्रस्तुत किया जाता है ... जब तक कि आपका कॉल स्टैक अधिकतम नहीं हो जाता है –

+1

@RyanWheale मेरी इच्छा है कि मैं उस टिप्पणी को दस लाख बार ऊपर उठा सकूं :) – Icepickle

+0

धन्यवाद, यह समझ में आता है, मैंने नहीं सोचा कि – Karol

उत्तर

17

जब भी आप कोड जो एक render समारोह अंदर से setState कॉल्स दिखाई, यह मानव कनखजूरा फिल्म के रूप में भावनाओं के एक ही प्रकार का आह्वान करना चाहिए के लिए धन्यवाद। राज्य परिवर्तन केवल कुछ बदलते का एक परिणाम के रूप में होना चाहिए:

render() { 
    ... 
    this.setState({ 
     iconStyle: _props.iconStyle 
    }); 

    this.setState({ 
     style: _props.style 
    }); 
    ... 
} 

[उल्टी: उपयोगकर्ता एक बटन पर क्लिक किया, ब्राउज़र विंडो आकार दिया गया था, एक तस्वीर, लिया गया था आदि

यहाँ समस्या कोड है मेरे मुंह में]

उपर्युक्त कोड एक अनंत लूप का कारण बनता है क्योंकि setStaterender कहलाता है। चूंकि iconStyle और style प्रोप हैं, और प्रोप बदल नहीं सकते हैं, तो आपको अपने शुरुआती राज्य को बनाने के लिए उन प्रोपों का उपयोग करना चाहिए।

handleClick() { 
    this.setState({ 
    iconStyle: 'clicked' 
    }); 
} 

इस कारण होगा अपने घटक rerendered जा करने के लिए और:

getInitialState() { 
    return { 
     iconStyle: this.props.iconStyle, 
     style: this.props.style, 
     cursorPos: {}, 
    }; 
} 

बाद में, अगर किसी को एक बटन क्लिक करता है और आप iconStyle बदलना चाहते हैं, आप एक क्लिक हैंडलर जो अपने राज्य को अद्यतन करता पैदा करेगा नया राज्य परिलक्षित होगा।

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

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

+0

यह बहुत अच्छा है, धन्यवाद। लेकिन अब मैं, यह त्रुटियां प्राप्त कर रहा हूं: 1) चेतावनी: टैग पर अज्ञात प्रोप 'टेक्स्ट'। तत्व से इस प्रोप को हटा दें। 2) चेतावनी: असमर्थित शैली संपत्ति पृष्ठभूमि रंग। क्या आपका मतलब पृष्ठभूमि रंग था? 'आइकन बटन' की रेंडर विधि देखें। वे – Karol

+0

से पहले नहीं थे, वे एक अलग मुद्दे हैं लेकिन डीबग करना आसान होना चाहिए। मुझे "टेक्स्ट" प्रोप के बारे में निश्चित नहीं है - ऐसा लगता है कि आप इसका उपयोग नहीं कर रहे हैं। इसके अलावा, प्रतिक्रिया में शैलियों को जावास्क्रिप्ट नाम का उपयोग करना चाहिए। मूल रूप से 'पृष्ठभूमि-रंग' 'पृष्ठभूमि रंग 'बन जाता है,' सीमा-चौड़ाई '' सीमा चौड़ाई' बन जाती है। यह सामान्य प्रतिक्रिया सामग्री है। –

+0

एक और संकेत जो मैं आपको दूंगा वह यह है कि आपके टूलटिप की दृश्यता आपके राज्य का हिस्सा होनी चाहिए। प्रारंभ में, टूलटिप IVisible गलत होना चाहिए। जब उपयोगकर्ता बटन क्लिक करता है, तो आपको सेटस्टेट को कॉल करना चाहिए और मान को सत्य पर सेट करना चाहिए। ऐसा करने से आपके घटक को फिर से प्रस्तुत किया जा सकता है। अपने 'रेंडर' फ़ंक्शन के अंदर आप इस चर को जांचेंगे और तदनुसार टूलटिप प्रस्तुत करेंगे। –

4

@RyanWheale के लिए धन्यवाद मैंने अपनी गलती देखी।

मेरे प्रस्तुत समारोह में मैं एक बटन तत्व लौटा रहा था जिसे एक फ़ंक्शन कहा जाता था जिसने एक निश्चित स्थिति को बदल दिया।

<button onclick={this.edit()} className="button-primary">Edit</button> 

और मेरे edit समारोह कुछ राज्य बदलता है और इस तरह दिखता है: लौटे बटन इस तरह देखा

edit: function() { 
    this.setState({editing: true}); 
} 

तो, मैं अपनी गलती है कि मैं, गलती से, कोष्टक this.edit के बाद आपके द्वारा लिखा गया, तो अराजकता हुई। अब, जब मैं

<button onclick={this.edit} className="button-primary">Edit</button>

बजाय

<button onclick={this.edit()} className="button-primary">Edit</button>

ने लिखा कि यह निर्दोष काम किया। मुझे आशा है कि मैं किसी को उसकी बहुमूल्य जिंदगी के घंटों को बचाने में मदद करूंगा।

चीयर्स :)

+1

आह, यह अनिवार्य रूप से वही बात है जो 'सेटस्टेट' को रेंडर फ़ंक्शन के अंदर से कॉल करने जैसा ही है। अच्छी पकड़। –

+0

धन्यवाद, और आपके बहुमूल्य उत्तर के लिए फिर से धन्यवाद। :) –

संबंधित मुद्दे