javascript - ماهو - react.js download




حلقة داخل React JSX (20)

ES2015 Array.from مع وظيفة الخريطة + مفتاح

إذا لم يكن لديك أي شيء .map() يمكنك استخدام Array.from() مع mapFn لتكرار العناصر:

<tbody>
  {Array.from({ length: 5 }, (v, k) => <ObjectRow key={k} />)}
</tbody>

أحاول أن أفعل شيئًا مثل ما يلي في React JSX (حيث يكون ObjectRow مكونًا منفصلاً):

<tbody>
    for (var i=0; i < numrows; i++) {
        <ObjectRow/>
    } 
</tbody>

أدرك وفهم سبب عدم صحة JSX ، نظرًا لأن JSX يعمل على تعيين المكالمات. ومع ذلك ، وأنا قادم من نموذج القالب وكوني جديدًا في JSX ، فأنا غير متأكد من كيفية تحقيق ما ورد أعلاه (إضافة مكون عدة مرات).


... أو يمكنك أيضًا إعداد مصفوفة من الكائنات وتعيينها إلى إحدى الوظائف للحصول على الإخراج المطلوب. أنا أفضل هذا ، لأنه يساعدني على الحفاظ على الممارسة الجيدة للترميز دون منطق داخل عودة تقديم.

render() {
const mapItem = [];
for(let i =0;i<item.length;i++) 
  mapItem.push(i);
const singleItem => (item, index) {
 // item the single item in the array 
 // the index of the item in the array
 // can implement any logic here
 return (
  <ObjectRow/>
)

}
  return(
   <tbody>{mapItem.map(singleItem)}</tbody>
  )
}

أميل إلى تفضيل نهج حيث منطق البرمجة يحدث خارج قيمة الإرجاع. هذا يساعد على الحفاظ على ما هو في الواقع من السهل تقديمه.

لذا من المحتمل أن أفعل شيئًا مثل:

import _ from 'lodash';

...

const TableBody = ({ objects }) => {
  const objectRows = objects.map(obj => <ObjectRow object={obj} />);      

  return <tbody>{objectRows}</tbody>;
} 

من المسلم به أن هذا هو كمية صغيرة من التعليمات البرمجية التي قد تعمل بشكل جيد.


أنا استخدمها مثل

<tbody>
{ numrows ? (
   numrows.map(obj => { return <ObjectRow /> }) 
) : null}
</tbody>

إذا كان numrows صفيفًا ، وهو بسيط جدًا.

<tbody>
   {numrows.map(item => <ObjectRow />)}
</tbody>

نوع بيانات المصفوفة في React هو الأفضل ، يمكن للمصفوفة أن تدعم مجموعة جديدة ، وفلتر الدعم ، وتقليل الخ.


إذا كنت تستخدم بالفعل ، فإن الدالة _.times مفيدة.

import React, { Component } from 'react';
import Select from './Select';
import _ from 'lodash';

export default class App extends Component {
    render() {
        return (
            <div className="container">
                <ol>
                    {_.times(3, i =>
                        <li key={i}>
                            <Select onSelect={this.onSelect}>
                                <option value="1">bacon</option>
                                <option value="2">cheez</option>
                            </Select>
                        </li>
                    )}
                </ol>
            </div>
        );
    }
}

استخدام وظيفة Map Array هو طريقة شائعة جدًا لإجراء حلقة صفيف من العناصر وإنشاء مكونات وفقًا لها في React ، وهي طريقة رائعة للقيام بحلقة وهي طريقة فعالة ومرتبة لتنفيذ الحلقات في JSX ، وهي ليست الوحيدة طريقة للقيام بذلك ، ولكن الطريقة المفضلة.

لا تنس أيضًا وجود مفتاح فريد لكل تكرار كما هو مطلوب. تعمل وظيفة الخريطة على إنشاء فهارس فريدة من 0 ولكن لا يُنصح باستخدام الفهرس ، ولكن إذا كانت قيمتك فريدة أو إذا كان هناك مفتاح فريد ، فيمكنك استخدامها:

<tbody>
  {numrows.map(x=> <ObjectRow key={x.id} />)}
</tbody>

أيضًا عدد قليل من الخطوط من MDN إذا لم تكن معتادًا على وظيفة الخريطة في Array:

تستدعي الخريطة وظيفة معاودة الاتصال مرة واحدة لكل عنصر في صفيف ، بالترتيب ، وتبني مصفوفة جديدة من النتائج. يتم استدعاء رد الاتصال فقط من أجل فهارس الصفيف التي لها قيم معينة ، بما في ذلك غير محددة. لا يتم استدعاؤه لعناصر المصفوفة المفقودة (أي الفهارس التي لم يتم تعيينها أبداً ، والتي تم حذفها أو التي لم يتم تعيين قيمة لها).

يتم استدعاء معاودة الاتصال مع ثلاث وسائط: قيمة العنصر ، وفهرس العنصر ، وجسم صفيف يتم اجتيازه.

إذا تم توفير معلمة thisArg للخريطة ، فسيتم استخدام هذه القيمة كميزة معاودة الاتصال. بخلاف ذلك ، سيتم استخدام القيمة غير المعرفة كقيمة لهذه القيمة. يتم تحديد هذه القيمة التي يمكن ملاحظتها في النهاية عن طريق معاودة الاتصال وفقًا للقواعد المعتادة لتحديد ما تراه إحدى الوظائف.

لا تقوم الخريطة بتحوير المصفوفة التي يطلق عليها (على الرغم من أن معاودة الاتصال ، إذا تم استدعاءها ، قد تفعل ذلك).


انا استعمل هذا:

gridItems = this.state.applications.map(app =>
                            <ApplicationItem key={app.Id} app={app } />
                            );

PD: أبدا ننسى المفتاح أو سيكون لديك الكثير من التحذيرات!


تستخدم إمكانية ES2015 / Babel وظيفة المولد لإنشاء صفيف من JSX:

function* jsxLoop(times, callback)
{
    for(var i = 0; i < times; ++i)
        yield callback(i);
}

...

<tbody>
    {[...jsxLoop(numrows, i =>
        <ObjectRow key={i}/>
    )]}
</tbody>

سؤال عظيم.

ما أقوم به عندما أريد إضافة عدد معين من المكونات هو استخدام وظيفة المساعد.

حدد وظيفة تقوم باعادة JSX:

const myExample = () => {
    let myArray = []
    for(let i = 0; i<5;i++) {
        myArray.push(<MyComponent/>)
    }
    return myArray
}

//... in JSX

<tbody>
    {myExample()}
</tbody>

سيتم ترجمة شفرة ReactElement إلى شفرة جافا سكريبت خالصة ، وسيتم استبدال أية علامات ReactElement . في JavaScript ، لا يمكنك استدعاء دالة عدة مرات لتجميع المتغيرات التي تم إرجاعها.

إنه غير قانوني ، الطريقة الوحيدة هي استخدام صفيف لتخزين المتغيرات التي يتم إرجاعها.

أو يمكنك استخدام map والذي يتوفر منذ JavaScript ES5 للتعامل مع هذا الموقف.

ربما يمكننا أن نكتب مترجمًا آخر لإعادة إنشاء بنية JSX جديدة لتنفيذ وظيفة تكرار تمامًا مثل تكرار Angular في Angular .


فكر في الأمر وكأنك فقط تتصل بوظائف JavaScript. لا يمكنك وضع حلقة for داخل حلقة استدعاء دالة:

return tbody(
    for (var i = 0; i < numrows; i++) {
        ObjectRow()
    } 
)

ولكن يمكنك إنشاء صفيف ، ثم تمرير ذلك في:

var rows = [];
for (var i = 0; i < numrows; i++) {
    rows.push(ObjectRow());
}
return tbody(rows);

يمكنك استخدام البنية نفسها في الأساس عند العمل مع JSX:

var rows = [];
for (var i = 0; i < numrows; i++) {
    // note: we add a key prop here to allow react to uniquely identify each
    // element in this array. see: https://reactjs.org/docs/lists-and-keys.html
    rows.push(<ObjectRow key={i} />);
}
return <tbody>{rows}</tbody>;

وبالمناسبة ، فإن مثال جافا سكريبت الخاص بي هو تقريبا بالضبط ما يتحول هذا المثال إلى JSX. العب مع Babel REPL للتعرف على كيفية عمل JSX.


لست متأكدا ما إذا كان هذا سيعمل لموقفك ، ولكن في كثير من الأحيان map هي إجابة جيدة.

إذا كانت هذه هي شفرتك مع حلقة for:

<tbody>
    for (var i=0; i < objects.length; i++) {
        <ObjectRow obj={objects[i]} key={i}>
    } 
</tbody>

يمكنك أن تكتبها هكذا مع map :

<tbody>
    {objects.map(function(object, i){
        return <ObjectRow obj={object} key={i} />;
    })}
</tbody>

بنية ES6:

<tbody>
    {objects.map((object, i) => <ObjectRow obj={object} key={i} />)}
</tbody>

لنفترض أن لدينا مجموعة من العناصر في ولايتك:

[{name: "item1", id: 1}, {name: "item2", id: 2}, {name: "item3", id: 3}]

<tbody>
    {this.state.items.map((item) => {
        <ObjectRow key={item.id} name={item.name} />
    })} 
</tbody>

نظرًا لأنك تكتب صياغة جافا سكريبت داخل شفرة JSX ، يجب أن تقوم بتغليف جافا سكريبت في أقواس معقوفة.

row = () => {
   var rows = [];
   for (let i = 0; i<numrows; i++) {
       rows.push(<ObjectRow/>);
   }
   return rows;
}
<tbody>
{this.row()}  
</tbody>

هناك طرق متعددة للقيام بذلك. يتم تجميع JSX في النهاية إلى جافا سكريبت ، طالما أنك تكتب لغة جافا سكريبت صالحة ، فستكون جيدًا.

تهدف إجابتي إلى دمج جميع الطرق الرائعة التي تم تقديمها هنا:

إذا لم يكن لديك مجموعة من الكائنات ، ببساطة عدد الصفوف:

داخل كتلة return ، وإنشاء Array واستخدام Array.prototype.map :

render() {
  return (
    <tbody>
      {Array(numrows).fill(null).map((value, index) => (
        <ObjectRow key={index}>
      ))}
    </tbody>
  );
}

خارج كتلة return ، ما عليك سوى استخدام JavaScript for-loop العادي:

render() {
  let rows = [];
  for (let i = 0; i < numrows; i++) {
    rows.push(<ObjectRow key={i}/>);
  } 
  return (
    <tbody>{rows}</tbody>
  );
}

على الفور استدعاء وظيفة التعبير:

render() {
  return (
    <tbody>
      {() => {
        let rows = [];
        for (let i = 0; i < numrows; i++) {
          rows.push(<ObjectRow key={i}/>);
        }
        return rows;
      }}
    </tbody>
  );
}

إذا كان لديك مجموعة من الكائنات

داخل كتلة return .map() كل كائن إلى مكون <ObjectRow> :

render() {
  return (
    <tbody>
      {objectRows.map((row, index) => (
        <ObjectRow key={index} data={row} />
      ))}
    </tbody>
  );
}

خارج كتلة return ، ما عليك سوى استخدام JavaScript for-loop العادي:

render() {
  let rows = [];
  for (let i = 0; i < objectRows.length; i++) {
    rows.push(<ObjectRow key={i} data={objectRows[i]} />);
  } 
  return (
    <tbody>{rows}</tbody>
  );
}

على الفور استدعاء وظيفة التعبير:

render() {
  return (
    <tbody>
      {() => {
        let rows = [];
        for (let i = 0; i < objectRows.length; i++) {
          rows.push(<ObjectRow key={i} data={objectRows[i]} />);
        }
        return rows;
      }}
    </tbody>
  );
}

وهنا حل بسيط لذلك.

var Object_rows=[];
for (var i=0; i < numrows; i++) {
    Object_rows.push(<ObjectRow/>)
} 
<tbody>
{Object_rows}
</tbody>

لا تحتاج إلى تخطيط ورمز معقد. تحتاج فقط إلى دفع الصفوف إلى صفيف وإرجاع القيم لعرضها.


ويمكن القيام بذلك بطرق متعددة.

  1. كما هو موضح أعلاه ، قبل أن يقوم return تخزين كافة العناصر في الصفيف
  2. حلقة داخل return

    طريقة 1

     let container =[];
        let arr = [1,2,3] //can be anything array, object 
    
        arr.forEach((val,index)=>{
          container.push(<div key={index}>
                         val
                         </div>)
            /** 
            * 1. All loop generated elements require a key 
            * 2. only one parent element can be placed in Array
            * e.g. container.push(<div key={index}>
                                        val
                                  </div>
                                  <div>
                                  this will throw error
                                  </div>  
                                )
            **/   
        });
        return (
          <div>
             <div>any things goes here</div>
             <div>{container}</div>
          </div>
        )
    

    الطريقة الثانية

       return(
         <div>
         <div>any things goes here</div>
         <div>
            {(()=>{
              let container =[];
              let arr = [1,2,3] //can be anything array, object 
              arr.forEach((val,index)=>{
                container.push(<div key={index}>
                               val
                               </div>)
                             });
                        return container;     
            })()}
    
         </div>
      </div>
    )
    

يمكنك أيضًا استخراج خارج كتلة الإرجاع:

render: function() {
    var rows = [];
    for (var i = 0; i < numrows; i++) {
        rows.push(<ObjectRow key={i}/>);
    } 

    return (<tbody>{rows}</tbody>);
}

يمكنك بالطبع حل مع .map كما اقترحه الجواب الآخر. إذا كنت تستخدم بالفعل babel ، فيمكنك التفكير في استخدام jsx-control-statements فهي تتطلب القليل من الإعداد ، ولكن أعتقد أنه يستحق القراءة من حيث قابلية القراءة (خاصة للمطورين الذين لا يتفاعلون). إذا كنت تستخدم eslint-plugin-jsx-control-statements ، فهناك أيضًا eslint-plugin-jsx-control-statements





reactjs