कैसे प्रतिक्रिया घटकों पर बल जबरदस्ती करने के लिए?


103

कहते हैं कि मेरे पास एक दृश्य घटक है जिसमें एक सशर्त रेंडर है:

render(){
    if (this.state.employed) {
        return (
            <div>
                <MyInput ref="job-title" name="job-title" />
            </div>
        );
    } else {
        return (
            <div>
                <MyInput ref="unemployment-reason" name="unemployment-reason" />
                <MyInput ref="unemployment-duration" name="unemployment-duration" />
            </div>
        );
    }
}

MyInput कुछ इस तरह दिखता है:

class MyInput extends React.Component {

    ...

    render(){
        return (
            <div>
                <input name={this.props.name} 
                    ref="input" 
                    type="text" 
                    value={this.props.value || null}
                    onBlur={this.handleBlur.bind(this)}
                    onChange={this.handleTyping.bind(this)} />
            </div>
        );
    }
}

कहते हैं employed, सच है। जब भी मैं इसे गलत पर स्विच करता हूं और अन्य दृश्य रेंडर करता है, तो केवल unemployment-durationपुन: प्रारंभ किया जाता है। इसके अलावा unemployment-reasonमूल्य से पूर्वनिर्धारित हो जाता है job-title(यदि स्थिति बदलने से पहले एक मूल्य दिया गया था)।

अगर मैं दूसरी रुटीन रूटीन में मार्कअप को कुछ इस तरह से बदलूँ:

render(){
    if (this.state.employed) {
        return (
            <div>
                <MyInput ref="job-title" name="job-title" />
            </div>
        );
    } else {
        return (
            <div>
                <span>Diff me!</span>
                <MyInput ref="unemployment-reason" name="unemployment-reason" />
                <MyInput ref="unemployment-duration" name="unemployment-duration" />
            </div>
        );
    }
}

ऐसा लगता है जैसे सब कुछ ठीक काम करता है। ऐसा लगता है कि रिएक्ट 'जॉब-टाइटल' और 'बेरोजगारी-कारण' को अलग करने में विफल है।

कृपया बताएं कि मैं क्या गलत कर रहा हूं ...


1
स्विच के पहले और बाद में (या जैसा कि DOM में देखा गया है) तत्वों में से data-reactidप्रत्येक पर क्या है ? MyInputinputemployed
क्रिस

@ क्रिस मैं यह निर्दिष्ट करने में विफल रहा कि MyInput- घटक एक में लिपटे इनपुट को प्रस्तुत करता है <div>data-reactidगुण दोनों रैपिंग div और इनपुट क्षेत्र पर अलग हो रहा है। job-titleइनपुट आईडी हो जाता है data-reactid=".0.1.1.0.1.0.1", जबकि unemployment-reasonइनपुट आईडीdata-reactid=".0.1.1.0.1.2.1"
o01

1
और किस बारे में unemployment-duration?
क्रिस

@ क्रिस सॉरी, मैंने बहुत जल्द बात की। पहले उदाहरण में ("मुझे अलग करें" स्पैन के बिना) reactidविशेषताएँ समान हैं job-titleऔर unemployment-reason, जबकि दूसरे उदाहरण में (डिफरेंट स्पैन के साथ) वे अलग हैं।
o01

के लिए @Chris विशेषता हमेशा अद्वितीय है। unemployment-durationreactid
o01

जवाबों:


108

संभवतः यह हो रहा है कि रिएक्ट सोचता है कि रेंडर के बीच केवल एक MyInput( unemployment-duration) जोड़ा जाता है। जैसे, job-titleकभी नहीं के साथ बदल दिया जाता है unemployment-reason, यही वजह है कि पूर्वनिर्धारित मूल्यों की अदला-बदली की जाती है।

जब प्रतिक्रिया भिन्न होती है, तो यह निर्धारित करेगा कि कौन से घटक नए हैं और जो उनकी keyसंपत्ति के आधार पर पुराने हैं। यदि कोड में ऐसी कोई कुंजी प्रदान नहीं की गई है, तो यह स्वयं उत्पन्न होगी।

आपके द्वारा प्रदान किए गए अंतिम कोड स्निपेट के कारण का कारण यह है कि प्रतिक्रिया के लिए मूल रूप से मूल तत्व के तहत सभी तत्वों के पदानुक्रम को बदलने की आवश्यकता होती है divऔर मेरा मानना ​​है कि यह सभी बच्चों के पुन: रेंडर को ट्रिगर करेगा (यही कारण है कि यह काम करता है)। अगर आपने spanऊपर के बजाय नीचे से जोड़ दिया होता , तो पूर्ववर्ती तत्वों के पदानुक्रम में बदलाव नहीं होता, और वे तत्व पुन: रेंडर नहीं करते (और समस्या बनी रहती)।

यहाँ आधिकारिक प्रतिक्रिया दस्तावेज क्या कहते हैं:

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

जब React कुंजीबद्ध बच्चों को समेट लेता है, तो यह सुनिश्चित करेगा कि कुंजी वाला कोई भी बच्चा पुन: व्यवस्थित किया जाएगा (क्लोब किए गए के बजाय) या नष्ट (पुन: उपयोग के बजाय)।

आपको इसे keyस्वयं या माता div- पिता या सभी MyInputतत्वों को एक विशिष्ट तत्व प्रदान करके इसे ठीक करने में सक्षम होना चाहिए ।

उदाहरण के लिए:

render(){
    if (this.state.employed) {
        return (
            <div key="employed">
                <MyInput ref="job-title" name="job-title" />
            </div>
        );
    } else {
        return (
            <div key="notEmployed">
                <MyInput ref="unemployment-reason" name="unemployment-reason" />
                <MyInput ref="unemployment-duration" name="unemployment-duration" />
            </div>
        );
    }
}

या

render(){
    if (this.state.employed) {
        return (
            <div>
                <MyInput key="title" ref="job-title" name="job-title" />
            </div>
        );
    } else {
        return (
            <div>
                <MyInput key="reason" ref="unemployment-reason" name="unemployment-reason" />
                <MyInput key="duration" ref="unemployment-duration" name="unemployment-duration" />
            </div>
        );
    }
}

अब, जब रिएक्ट अलग होता है, तो यह देखेगा कि divsअलग हैं और अपने सभी बच्चों (1 उदाहरण) सहित इसे फिर से प्रस्तुत करेंगे। 2 उदाहरण में, अंतर एक सफलता होगी job-titleऔर unemployment-reasonचूंकि अब उनके पास अलग-अलग कुंजी हैं।

आप निश्चित रूप से किसी भी कुंजी का उपयोग कर सकते हैं जिसे आप चाहते हैं, जब तक कि वे अद्वितीय हैं।


अगस्त 2017 को अपडेट करें

रिएक्ट में कुंजियाँ कैसे काम करती हैं, इसकी बेहतर जानकारी के लिए, मैं दृढ़ता से React.js में अद्वितीय कुंजियों को समझने के लिए अपने उत्तर को पढ़ने की सलाह देता हूँ


अपडेट नवंबर 2017

इस अद्यतन को कुछ समय पहले पोस्ट किया जाना चाहिए था, लेकिन refअब इसमें स्ट्रिंग शाब्दिक का उपयोग किया गया है। उदाहरण के लिए ref="job-title"अब होना चाहिए ref={(el) => this.jobTitleRef = el}(उदाहरण के लिए)। अधिक जानकारी के लिए this.refs का उपयोग करके डिप्रेसेशन चेतावनी के लिए मेरा उत्तर देखें ।


10
it will determine which components are new and which are old based on their key property.- कि था ... कुंजी ... मेरी समझ के लिए
लैरी

1
आपका बहुत बहुत धन्यवाद ! मुझे यह भी पता चल गया था कि एक नक्शे से सभी बच्चों के घटकों को फिर से सफलतापूर्वक प्रदान किया गया था और मुझे समझ नहीं आया कि क्यों।
वैलेंटाइनविलेन

एक अच्छा संकेत एक राज्य चर (जो बदलता है, जैसे आईडी के लिए जैसे।) का उपयोग करना है।
मैकलियास 14

200

घटक की कुंजी बदलें।

<Component key="1" />
<Component key="2" />

घटक असम्बद्ध किया जाएगा और घटक का एक नया उदाहरण आरोहित होगा क्योंकि कुंजी बदल गई है।

संपादित करें : आपके द्वारा प्रलेखित संभवतः राज्य की आवश्यकता नहीं है :

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


45
यह रिएक्ट प्रलेखन में अधिक स्पष्ट होना चाहिए। यह वही था जो मैं बाद में था, लेकिन खोजने में घंटों लग गए।
पॉल

4
खैर इससे मुझे बहुत फायदा हुआ! धन्यवाद! मुझे एक सीएसएस एनीमेशन को रीसेट करने की आवश्यकता थी लेकिन ऐसा करने का एकमात्र तरीका फिर से रेंडर करने के लिए मजबूर करना है। मैं सहमत हूं कि प्रतिक्रिया दस्तावेज में यह अधिक स्पष्ट होना चाहिए
एलेक्स। पी।

@ Alex.P। अच्छा! सीएसएस एनिमेशन कभी-कभी मुश्किल हो सकते हैं। मैं एक उदाहरण देखना चाहूंगा।
एलेक्स के।

1
इस तकनीक का वर्णन करने वाले रिएक्ट डॉक्यूमेंटेशन: reactjs.org/blog/2018/06/07/…
GameSalutes

धन्यवाद। मैं इसके लिए बहुत आभारी हूं। मैंने "यादृच्छिकनंबर" जैसे अघोषित प्रॉप्स को यादृच्छिक संख्याओं को खिलाने की कोशिश की, लेकिन जो एकमात्र काम किया वह महत्वपूर्ण था।
शमवारे

5

राज्य की संपत्ति setStateबदलने के लिए अपने दृष्टिकोण में उपयोग करें employed। यह React रेंडर इंजन का उदाहरण है।

 someFunctionWhichChangeParamEmployed(isEmployed) {
      this.setState({
          employed: isEmployed
      });
 }

 getInitialState() {
      return {
          employed: true
      }
 },

 render(){
    if (this.state.employed) {
        return (
            <div>
                <MyInput ref="job-title" name="job-title" />
            </div>
        );
    } else {
        return (
            <div>
                <span>Diff me!</span>
                <MyInput ref="unemployment-reason" name="unemployment-reason" />
                <MyInput ref="unemployment-duration" name="unemployment-duration" />
            </div>
        );
    }
}

मैं पहले से ही ऐसा कर रहा हूं। 'नियोजित' चर दृश्य घटक राज्य का हिस्सा है, और इसे सेटस्टैट फ़ंक्शन के माध्यम से बदल दिया जाता है। यह नहीं समझाने के लिए क्षमा करें।
o01

'नियोजित' चर अभिक्रिया अवस्था की संपत्ति होनी चाहिए। यह आपके कोड उदाहरण में स्पष्ट नहीं है।
दिमित्री

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

मेरे उदाहरण शो की तुलना में दृश्य घटक थोड़ा अधिक जटिल है। MyInput- घटकों के अलावा, यह एक रेडियोबॉटन समूह को भी प्रस्तुत करता है जो ऑनकॉन्ग हैंडलर के साथ 'नियोजित' के मूल्य को नियंत्रित करता है। OnChange हैंडलर में, मैं तदनुसार दृश्य घटक की स्थिति सेट करता हूं। जब रेडियोबूटन समूह का मान बदलता है, तो दृश्य फिर से ठीक हो जाता है, लेकिन रिएक्ट को लगता है कि पहला माई इनपुट-कंपोनेंट वैसा ही है जैसा कि 'नियोजित' परिवर्तित होने से पहले था।
o01

0

मैं अपने ऐप के लिए क्रूड पर काम कर रहा हूं। यह है कि मैंने अपनी निर्भरता के रूप में इसे कैसे किया है।

import React, { useState, setState } from 'react';
import 'bootstrap/dist/css/bootstrap.min.css';
import firebase from 'firebase';
// import { LifeCrud } from '../CRUD/Crud';
import { Row, Card, Col, Button } from 'reactstrap';
import InsuranceActionInput from '../CRUD/InsuranceActionInput';

const LifeActionCreate = () => {
  let [newLifeActionLabel, setNewLifeActionLabel] = React.useState();

  const onCreate = e => {
    const db = firebase.firestore();

    db.collection('actions').add({
      label: newLifeActionLabel
    });
    alert('New Life Insurance Added');
    setNewLifeActionLabel('');
  };

  return (
    <Card style={{ padding: '15px' }}>
      <form onSubmit={onCreate}>
        <label>Name</label>
        <input
          value={newLifeActionLabel}
          onChange={e => {
            setNewLifeActionLabel(e.target.value);
          }}
          placeholder={'Name'}
        />

        <Button onClick={onCreate}>Create</Button>
      </form>
    </Card>
  );
};

कुछ रिएक्ट हुक वहाँ


एसओ में आपका स्वागत है! आप एक अच्छे उत्तर को लिखने के तरीके की समीक्षा करना चाहते हैं । कुछ स्पष्टीकरण जोड़ें कि आपने कोड को पोस्ट करने से परे प्रश्न को कैसे हल किया।
विस्थापित
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.