मैं दोहराने वाले तत्वों को कैसे प्रस्तुत कर सकता हूं?


81

मैंने ReactJS में दोहराए जाने वाले तत्वों को प्रस्तुत करने के लिए कुछ कोड लिखे हैं, लेकिन मुझे लगता है कि यह कितना बदसूरत है।

render: function(){
  var titles = this.props.titles.map(function(title) {
    return <th>{title}</th>;
  });
  var rows = this.props.rows.map(function(row) {
    var cells = [];
    for (var i in row) {
      cells.push(<td>{row[i]}</td>);
    }
    return <tr>{cells}</tr>;
  });
  return (
    <table className="MyClassName">
      <thead>
        <tr>{titles}</tr>
      </thead>
      <tbody>{rows}</tbody>
    </table>
  );
} 

क्या इसे प्राप्त करने का एक बेहतर तरीका है?

(मैं forटेम्पलेट कोड, या कुछ इसी तरह के दृष्टिकोण के भीतर छोरों को एम्बेड करना चाहूंगा ।)


2
क्या आप ऐसा कुछ करना चाहते हैं? stackoverflow.com/questions/22876978/loop-inside-react-jsx
patricK

3
हां, यह कि मैं क्या चाहता हूं, लेकिन स्वीकृत उत्तर बहुत ही बदसूरत कोड के समान है जो मैं पहले से लिख रहा हूं। एक बेहतर तरीका होना चाहिए ...
febbee

मुझे आशा है कि यह stackoverflow.com/a/37600679/1785635
abhirathore2006

जवाबों:


130

आप ब्रेसिज़ के अंदर भाव रख सकते हैं। संकलित जावास्क्रिप्ट में नोटिस क्यों forजेएसएक्स सिंटैक्स के अंदर एक लूप कभी संभव नहीं होगा; JSX राशियाँ कॉल और सुगर फंक्शन दलीलें करने के लिए। केवल अभिव्यक्ति की अनुमति है।

(इसके अलावा keyछोरों के अंदर प्रदान किए गए घटकों के लिए विशेषताओं को जोड़ना याद रखें ।)

JSX + ES2015 :

render() {
  return (
    <table className="MyClassName">
      <thead>
        <tr>
          {this.props.titles.map(title =>
            <th key={title}>{title}</th>
          )}
        </tr>
      </thead>
      <tbody>
        {this.props.rows.map((row, i) =>
          <tr key={i}>
            {row.map((col, j) =>
              <td key={j}>{col}</td>
            )}
          </tr>
        )}
      </tbody>
    </table>
  );
} 

जावास्क्रिप्ट :

render: function() {
  return (
    React.DOM.table({className: "MyClassName"}, 
      React.DOM.thead(null, 
        React.DOM.tr(null, 
          this.props.titles.map(function(title) {
            return React.DOM.th({key: title}, title);
          })
        )
      ), 
      React.DOM.tbody(null, 
        this.props.rows.map(function(row, i) {
          return (
            React.DOM.tr({key: i}, 
              row.map(function(col, j) {
                return React.DOM.td({key: j}, col);
              })
            )
          );
        })
      )
    )
  );
} 

अच्छा कैच। मैंने शीर्ष पर लापता कोष्ठक जोड़ा और forए से स्विच किया map। चूंकि मुझे नहीं पता है कि डेटा संरचनाओं में से प्रत्येक में डेटा क्या है, मैंने मान लिया कि पंक्तियों को सरणियाँ हैं और इसे करने के लिए पुनरावृत्ति के सूचकांक का उपयोग किया key। जब डेटा को सरणी से जोड़ा / हटाया जाता है, तो यह अनावश्यक पुन: प्रतिपादन का कारण होगा। आपको keyउस मान पर स्विच करना चाहिए जो विशिष्ट रूप से डेटा की पहचान करता है और जो कि ऑर्डर और / या सरणी के आकार पर निर्भर नहीं है।
रॉस एलन

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

1
@chrisdew JSX टेम्प्लेट लैंग्वेज नहीं है, यह सादे पुराने जावास्क्रिप्ट के लिए सिंटैक्टिक शुगर है। आपको टेम्प्लेट भाषाओं से अपेक्षा के अनुरूप ऑपरेटर नहीं मिलेंगे। इस उत्तर में कोड को लाइव JSX कंपाइलर में चिपकाने की कोशिश करें ताकि यह समझ सकें कि यह क्या कर रहा है और क्यों forलूप कभी संभव नहीं होगा।
रॉस एलन

क्या आप प्रत्येक पंक्ति के लिए onClick घटना जोड़ सकते हैं और पंक्ति आइटम को फ़ंक्शन में पास कर सकते हैं? मैं कुछ इस तरह की कोशिश कर रहा हूं, लेकिन मुझे अनकैप्ड टाइपर्रर मिल रहा है: अपरिभाषित क्लिक हेंडलर की संपत्ति 'क्लिकहैंडलर' नहीं पढ़ सकता () {कंसोल.लॉग ('क्लिक रो पर'); } <tbody> {this.props.rows.map (function (row, i) {return (<tr key = {i} onClick = this.clickHandler ()> {row.map (function (col, j)) <td key = {j}> {col} </ td>;})} </ tr>);})} </ tbody>
किरण

कोई बात नहीं मैंने मानचित्र विधि में .bind (यह) जोड़ा है तो विधि प्रत्येक पंक्ति के लिए शामिल हो रही है। धन्यवाद।
किरण

13

रॉस एलेन के जवाब पर विस्तार करने के लिए, यहां ES6 तीर सिंटैक्स का उपयोग करके थोड़ा क्लीनर संस्करण है।

{this.props.titles.map(title =>
  <th key={title}>{title}</th>
)}

इसका यह फायदा है कि JSX हिस्सा अलग-थलग (नहीं returnया ;) है, जिससे इसके चारों ओर एक लूप लगाना आसान हो जाता है।


13

चूंकि Array(3)यह एक गैर-पुनरावृत्ति सरणी बनाएगा , इसलिए इसे mapऐरे पद्धति के उपयोग की अनुमति देने के लिए आबाद किया जाना चाहिए । "कन्वर्ट" करने का एक तरीका यह है कि इसे एरे-ब्रैकेट के अंदर नष्ट कर दिया जाए, जो एरे को "भर" कर undefinedदेता है, जैसे किArray(N).fill(undefined)

<table>
    { [...Array(3)].map((_, index) => <tr key={index}/>) }
</table>

एक और तरीका एरे के माध्यम से होगा fill():

<table>
    { Array(3).fill(<tr/>) }
</table>

Is उपरोक्त उदाहरण के साथ समस्या keyप्रोप की कमी है , जो एक जरूरी है
(पुनरावर्तक उपयोग कर रहा है indexके रूप में keyअनुशंसित नहीं है)


नेस्टेड नोड्स:

const tableSize = [3,4]
const Table = (
    <table>
        <tbody>
        { [...Array(tableSize[0])].map((tr, trIdx) => 
            <tr key={trIdx}> 
              { [...Array(tableSize[1])].map((a, tdIdx, arr) => 
                  <td key={trIdx + tdIdx}>
                  {arr.length * trIdx + tdIdx + 1}
                  </td>
               )}
            </tr>
        )}
        </tbody>
    </table>
);

ReactDOM.render(Table, document.querySelector('main'))
td{ border:1px solid silver; padding:1em; }
<script crossorigin src="https://unpkg.com/react@16/umd/react.development.js"></script>
<script crossorigin src="https://unpkg.com/react-dom@16/umd/react-dom.development.js"></script>
<main></main>


2
मैं कम से कम 2 घंटे खर्च करने के लिए पाश के अंदर पाश में सक्षम होना करने के लिए रेंडर समारोह। धन्यवाद। आपने मेरा दिन बचाया।
श्वेत

2
क्या आप उपयोग मानचित्र के बजाय ऐसा नहीं कर सकते थे? Array.from({length: 5}, (value, index) => <tr />)
क्रिएटिवहल

2

कार्यात्मक प्रोग्रामिंग की भावना में, हम अपने घटकों को अमूर्त का उपयोग करके काम करना थोड़ा आसान बनाते हैं।

// converts components into mappable functions
var mappable = function(component){
  return function(x, i){
    return component({key: i}, x);
  }
}

// maps on 2-dimensional arrays
var map2d = function(m1, m2, xss){
  return xss.map(function(xs, i, arr){
    return m1(xs.map(m2), i, arr);
  });
}

var td = mappable(React.DOM.td);
var tr = mappable(React.DOM.tr);
var th = mappable(React.DOM.th);

अब हम अपने रेंडर को इस तरह परिभाषित कर सकते हैं:

render: function(){
  return (
    <table>
      <thead>{this.props.titles.map(th)}</thead>
      <tbody>{map2d(tr, td, this.props.rows)}</tbody>
    </table>
  );
}

jsbin


हमारे map2d के लिए एक विकल्प एक करीबी नक्शा कार्य होगा, लेकिन लोग करीने से दूर भागते हैं।


वे कार्य देव को keyविशेषता निर्दिष्ट करने का अवसर नहीं देते हैं । अनुक्रमणिका का उपयोग करने का अर्थ है कि तत्वों को जोड़ना / हटाना उन वस्तुओं के लिए फिर से प्रतिपादन करने के लिए मजबूर करेगा जो बदल नहीं सकते हैं।
रॉस एलन

सही है, लेकिन सूचकांक आधारित कुंजी पर्याप्त समय का 95% है। मैं इसके बजाय कुछ हद तक दुर्लभ अपवादों से थोड़ा बाहर जाना चाहता हूँ।
ब्रिगैंड

सहमत, यह सुनिश्चित करना काफी आसान होगा कि कुंजी किसी भी स्तर पर अद्वितीय हैं यदि यह आवश्यक था, तो मुझे यह पसंद है।
रयान ओरे

2

यह, imo, इसे करने के लिए सबसे सुंदर तरीका है (ES6 के साथ)। एक पंक्ति में 7 अनुक्रमित और मानचित्र के साथ आपको खाली सरणी का संकेत दें:

Array.apply(null, Array(7)).map((i)=>
<Somecomponent/>
)

kudos से https://php.quicoto.com/create-loop-inside-react-jsx/


1
अच्छा लगा! लगता है आप भी कर सकते हैंArray(...Array(10)).map((v, i) => <SomeComponent />)
पत्रिका
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.