स्टेटलेस घटकों में कार्य?


93

मैं इस शांत <canvas>एनीमेशन को एक रिएक्ट पुन: प्रयोज्य घटक में यहाँ बदलने की कोशिश कर रहा हूँ । ऐसा लगता है कि इस घटक को कैनवास के लिए एक मूल घटक की आवश्यकता होगी, और कई बच्चों के घटकों के लिए function Ball()

प्रदर्शन के कारणों के लिए यह संभवत: बेहतर होगा कि Ballsवे स्टेटलेस घटकों को बनाएं क्योंकि उनमें से कई होंगे। मैं स्टेटलेस घटकों को बनाने के बारे में परिचित नहीं हूँ और सोच रहा था कि मुझे उन कार्यों this.update()और this.drawकार्यों को कैसे परिभाषित करना चाहिए जो में परिभाषित हैं function Ball()

क्या स्टेटलेस घटकों के लिए कार्य घटक के अंदर या बाहर जाते हैं? दूसरे शब्दों में, निम्नलिखित में से कौन बेहतर है?

1:

const Ball = (props) => {
    const update = () => {
        ...
    }

    const draw = () => {
        ...
    }

    return (
       ...
    );
}

2:

function update() {
     ...
}

function draw() {
     ...
}

const Ball = (props) => {
    return (
       ...
    );
}

प्रत्येक के पेशेवरों / विपक्ष क्या हैं और उनमें से एक विशिष्ट उपयोग के मामलों के लिए बेहतर हैं जैसे कि मेरा?


क्या आप मौजूदा कोड पोस्ट कर सकते हैं ताकि हम देखें कि इसका उपयोग कैसे होगा?
शिमोनस्टर

@Scimonster मैंने इसे एक एम्बेडेड लिंक में पोस्ट किया है, हो सकता है कि आपने इसे याद किया हो। : यहाँ लिंक है codepen.io/awendland/pen/XJExGv
MarksCode

जवाबों:


117

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

ज्यादातर मामलों में आपको घटक फ़ंक्शन के बाहर के कार्यों की घोषणा करनी चाहिए ताकि आप उन्हें केवल एक बार घोषित करें और हमेशा एक ही संदर्भ का उपयोग करें। जब आप फ़ंक्शन को अंदर घोषित करते हैं, तो हर बार घटक प्रदान किए जाने पर फ़ंक्शन को फिर से परिभाषित किया जाएगा।

ऐसे मामले हैं जिनमें आपको घटक के अंदर एक फ़ंक्शन को परिभाषित करने की आवश्यकता होगी, उदाहरण के लिए, इसे एक इवेंट हैंडलर के रूप में असाइन करें जो घटक के गुणों के आधार पर भिन्न व्यवहार करता है। लेकिन फिर भी आप फ़ंक्शन को बाहर से परिभाषित कर सकते हैं Ballऔर इसे गुणों के साथ बाँध सकते हैं, जिससे कोड बहुत अधिक क्लीनर बन जाएगा updateया फिर से drawपुन: प्रयोज्य हो सकता है।

// You can use update somewhere else
const update (propX, a, b) => { ... };

const Ball = props => (
  <Something onClick={update.bind(null, props.x)} />
);

यदि आप हुक का उपयोग कर रहे हैं , तो आप useCallbackयह सुनिश्चित करने के लिए उपयोग कर सकते हैं कि फ़ंक्शन केवल तब ही पुनर्परिभाषित हो जब इसकी निर्भरता ( props.xइस मामले में) परिवर्तन में से एक:

const Ball = props => {
  const onClick = useCallback((a, b) => {
    // do something with a, b and props.x
  }, [props.x]);

  return (
    <Something onClick={onClick} />
  );
}

यह गलत तरीका है :

const Ball = props => {
  function update(a, b) {
    // props.x is visible here
  }

  return (
    <Something onClick={update} />
  );
}

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


धन्यवाद मार्को, जो चीजों को थोड़ा साफ करता है। मेरे मामले में मैं जिस चीज को लेकर उलझन में हूं वह this.drawअंदर के फंक्शन से संबंधित है Ball। यह उस ctxचीज का उपयोग करता है जो माता-पिता की होती है <canvas>और यह भी thisबच्चे के Ballघटक के लिए कीवर्ड का उपयोग करता है । वैधानिक घटक को लागू करने का सबसे अच्छा तरीका क्या होगा ताकि उन दोनों संपत्तियों तक पहुंच हो सके?
मार्कसकोड

ऐसा नहीं है thisजब स्टेटलेस फंक्शनल कंपोनेंट्स का इस्तेमाल किया जाता है, तो यह ध्यान में रखना चाहिए। कैनवास संदर्भ के लिए, आपको इसे हर एक को पास करना होगा Ball, जो बिल्कुल अच्छा नहीं लगता है।
मार्को स्कैबियोलो

तो इस मामले में यह सबसे अच्छा होगा कि आपके पास कोई बच्चा घटक नहीं है जो आप कह रहे हैं?
मार्कसकोड

1
@MarcoScabbiolo नहीं नहीं, यह मेरा मामला नहीं है, पहले से ही काफी लंबे समय से मूल कार्यों का उपयोग कर रहा है, क्योंकि एकमात्र ब्राउज़र उनका समर्थन नहीं कर रहा है IE। वास्तव में मैं एक लेख से इस टिप्पणी को खोजने में कामयाब रहा, जहां यह वास्तव में दावा किया गया है कि bindविशेष रूप से क्रोम में 59 से पहले भी तीर कार्यों की तुलना में धीमी थी। और फ़ायरफ़ॉक्स में यह काफी समय से है क्योंकि वे दोनों एक ही गति के साथ प्रदर्शन करते हैं। तो मैं कहूंगा कि ऐसे मामलों में कोई अंतर नहीं है कि पसंदीदा तरीका क्या है :)
वादिम कलिनिन

1
@ MauricioAvendaño किसी भी तरह से काम करता है, लेकिन यह Somethingघटक के लिए यह जानने के लिए एक बुरा अभ्यास है कि इसके मूल घटक में एक प्रोप एक्स है क्योंकि यह इसके संदर्भ से अवगत कराता है। आपके द्वारा पूछे गए प्रश्न और आपके द्वारा लिखे गए नमूना कोड के लिए भी ऐसा ही होता है, यह संदर्भ पर निर्भर करता है, जिसे सरलता के लिए अनदेखा किया जाता है।
मार्को स्कैबियोलो

13

हम स्टेटलेस फंक्शनल घटकों के अंदर कार्य कर सकते हैं, नीचे उदाहरण है:

 const Action = () => {
  function  handlePick(){
     alert("test");
  }
  return (
    <div>
      <input type="button" onClick={handlePick} value="What you want to do ?" />
    </div>
  );
}

लेकिन, यह एक अच्छा अभ्यास नहीं है क्योंकि handlePick()घटक को कॉल करने पर फ़ंक्शन को हर बार परिभाषित किया जाएगा।


11
यदि इसका अच्छा अभ्यास नहीं है, तो वैकल्पिक समाधान क्या होगा?
जॉन सैमुअल

@JohnSamuel विकल्प handlePick()घटक के ऊपर / बाहर परिभाषित करने के लिए है जैसे function handlePick() { ... }; const Action = () => { ... }कि हैंडलपिक केवल एक बार परिभाषित किया जा रहा है। यदि आपको Actionघटक से डेटा की आवश्यकता है , तो आपको इसे handlePickफ़ंक्शन के पैरामीटर के रूप में पास करना चाहिए ।
जेम्स

14
यदि यह एक अच्छा अभ्यास नहीं है तो आप उत्तर के साथ अच्छा अभ्यास जोड़ सकते हैं? अब मुझे अच्छे अभ्यास के लिए फिर से खोज करनी होगी :(
शमसेर अहमद

2

हम useCallbackएक कार्यात्मक घटक में नीचे दिए गए रिएक्ट हुक का उपयोग कर सकते हैं :

const home = (props) => {
    const { small, img } = props
    const [currentInd, setCurrentInd] = useState(0);
    const imgArrayLength = img.length - 1;
    useEffect(() => {
        let id = setInterval(() => {
            if (currentInd < imgArrayLength) {
                setCurrentInd(currentInd => currentInd + 1)
            }
            else {
                setCurrentInd(0)
            }
        }, 5000);
        return () => clearInterval(id);
    }, [currentInd]);
    const onLeftClickHandler = useCallback(
        () => {
            if (currentInd === 0) {

            }
            else {
                setCurrentInd(currentInd => currentInd - 1)
            }
        },
        [currentInd],
    );

    const onRightClickHandler = useCallback(
        () => {
            if (currentInd < imgArrayLength) {
                setCurrentInd(currentInd => currentInd + 1)
            }
            else {

            }
        },
        [currentInd],
    );
    return (
        <Wrapper img={img[currentInd]}>
            <LeftSliderArrow className={currentInd > 0 ? "red" : 'no-red'} onClick={onLeftClickHandler}>
                <img src={Icon_dir + "chevron_left_light.png"}></img>
            </LeftSliderArrow>
            <RightSliderArrow className={currentInd < imgArrayLength ? "red" : 'no-red'} onClick={onRightClickHandler}>
                <img src={Icon_dir + "chevron_right_light.png"}></img>
            </RightSliderArrow>
        </Wrapper>);
}

export default home;

मुझे इसके माता-पिता से 'img' मिल रहा है और यह एक सरणी है।


1

यदि आप फ़ंक्शन में प्रॉप्स या कंपोनेंट की स्थिति का उपयोग करना चाहते हैं, तो उसे यूज़ किया जाना चाहिए जिसमें यूज़ किया गया है।

function Component(props){
  const onClick=useCallback(()=>{
     // Do some things with props or state
  },[])
}

दूसरी ओर, यदि आप फ़ंक्शन में प्रॉप्स या स्टेट का उपयोग नहीं करना चाहते हैं, तो घटक के बाहर परिभाषित करें।

const computeSomethings=()=>{
   // Do some things with params or side effects
}

function Component(props){
  
}

3
क्या आप कार्यात्मक घटक के अंदर विधि के लिए हुक का उपयोग करने का एक उदाहरण दे सकते हैं? (सेट नहीं राज्य विधि)
जेक-फर्ग्यूसन
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.