development

React JSX 내부 루프

big-blog 2020. 9. 27. 13:02
반응형

React JSX 내부 루프


React에서 다음과 같은 작업을 시도하고 있습니다 JSX(ObjectRow는 별도의 구성 요소입니다).

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

함수 호출에 매핑 JSX되기 때문에 이것이 유효하지 않은 이유를 알고 이해 JSX합니다. 그러나 템플릿 랜드에서 왔고을 (를 JSX) 처음 사용하는 경우 위의 작업을 수행하는 방법이 확실하지 않습니다 (구성 요소를 여러 번 추가).


JavaScript 함수를 호출하는 것처럼 생각하십시오. for함수 호출에 대한 인수가 이동 하는 루프를 사용할 수 없습니다 .

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

함수 tbodyfor루프를 인수로 전달하는 방법을 확인하십시오. 물론 이는 구문 오류입니다.

그러나 배열을 만든 다음 인수로 전달할 수 있습니다.

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>;

덧붙여서, 내 JavaScript 예제는 JSX 예제가 변환하는 것과 거의 동일합니다. 함께 놀러 바벨 REPL하는 JSX의 작동 방법에 대한 느낌을 얻을 수 있습니다.


이것이 귀하의 상황에 맞는지 확실하지 않지만 종종 지도 가 좋은 대답입니다.

이것이 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>

map()@FakeRainBrigand의 답변 좋아 하는 배열이 아직없고 소스 레이아웃이 @SophieAlpert의 답변보다 더 가까운 출력에 해당하도록 인라인하려면 다음을 수행하십시오.

ES2015 (ES6) 구문 사용 (확산 및 화살표 기능)

http://plnkr.co/edit/mfqFWODVy8dKQQOkIEGV?p=preview

<tbody>
  {[...Array(10)].map((x, i) =>
    <ObjectRow key={i} />
  )}
</tbody>

Re : Babel로 트랜스 파일하는 경우, 해당 경고 페이지Array.from 에 확산에 필요 하다고 나와 있지만 현재 ( v5.8.23)는 실제 Array. 나는이 문서의 문제 가를 명확히 열기를. 그러나 귀하의 책임하에 사용하거나 polyfill을 사용하십시오.

바닐라 ES5

Array.apply

<tbody>
  {Array.apply(0, Array(10)).map(function (x, i) {
    return <ObjectRow key={i} />;
  })}
</tbody>

인라인 IIFE

http://plnkr.co/edit/4kQjdTzd4w69g8Suu2hT?p=preview

<tbody>
  {(function (rows, i, len) {
    while (++i <= len) {
      rows.push(<ObjectRow key={i} />)
    }
    return rows;
  })([], 0, 10)}
</tbody>

다른 답변의 기술 조합

출력에 해당하는 소스 레이아웃을 유지하되 인라인 부분을 더 간결하게 만듭니다.

render: function () {
  var rows = [], i = 0, len = 10;
  while (++i <= len) rows.push(i);

  return (
    <tbody>
      {rows.map(function (i) {
        return <ObjectRow key={i} index={i} />;
      })}
    </tbody>
  );
}

ES2015 구문 및 Array방법 사용

으로 Array.prototype.fill당신이 전파를 사용하는 대신이 작업을 수행 할 수있는 위의 그림과 같이 :

<tbody>
  {Array(10).fill(1).map((el, i) =>
    <ObjectRow key={i} />
  )}
</tbody>

(실제로에 대한 인수를 생략 할 수 있다고 생각 fill()하지만 100 %는 아닙니다.) fill()솔루션 의 이전 버전에서 실수를 수정 한 @FakeRainBrigand에게 감사드립니다 (개정판 참조).

key

모든 경우에 key속성은 개발 빌드에서 경고를 완화하지만 자식에서는 액세스 할 수 없습니다. 자식에서 인덱스를 사용할 수 있도록하려면 추가 속성을 전달할 수 있습니다. 자세한 내용은 목록 및 키참조하십시오 .


ES6 구문으로 map Array 메서드를 사용하기 만하면 됩니다 .

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

key재산을 잊지 마십시오 .


사용 배열 맵 함수는 루프를 통해 매우 일반적인 방법입니다 배열 요소를 만들고 구성 요소가 그들에 따라 반작용 이 꽤 효율적에 루프 할 수있는 깔끔한 방법입니다 루프 할 수있는 좋은 방법입니다 JSX은 , 그건 하지 만 하지만 선호하는 방법입니다.

또한 필요에 따라 각 반복마다 고유 한 키갖는 것을 잊지 마십시오 . Map 함수 는 0에서 고유 인덱스를 생성하지만 생성 된 인덱스를 사용하는 것은 권장되지 않지만 값이 고유하거나 고유 한 키가있는 경우 사용할 수 있습니다.

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

또한 Array의 map 기능에 익숙하지 않은 경우 MDN의 몇 줄 :

map은 배열의 각 요소에 대해 제공된 콜백 함수를 순서대로 한 번씩 호출하고 결과에서 새 배열을 구성합니다. 콜백은 undefined를 포함하여 값이 할당 된 배열의 인덱스에 대해서만 호출됩니다. 배열의 누락 된 요소 (즉, 설정되지 않았거나 삭제되었거나 값이 할당되지 않은 인덱스)에 대해서는 호출되지 않습니다.

콜백은 요소의 값, 요소의 인덱스 및 순회되는 Array 객체의 세 가지 인수로 호출됩니다.

thisArg 매개 변수가 매핑에 제공되면 콜백의이 값으로 사용됩니다. 그렇지 않으면 undefined 값이이 값으로 사용됩니다. 콜백이 궁극적으로 관찰 할 수있는이 값은 함수에서 확인하는 일반적인 규칙에 따라 결정됩니다.

map은 호출 된 배열을 변경하지 않습니다 (콜백이 호출되면 그렇게 할 수 있음).


이미 lodash를 사용하고 있다면이 _.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>
        );
    }
}

리턴 블록 외부에서 추출 할 수도 있습니다.

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

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

이것이 오래된 스레드라는 것을 알고 있지만 React Templates 를 확인하고 싶을 수도 있습니다. React Templates 를 확인 하면 몇 가지 지시문 (예 : rt-repeat)과 함께 react에서 jsx 스타일 템플릿을 사용할 수 있습니다.

react-templates를 사용한 경우 예는 다음과 같습니다.

<tbody>
     <ObjectRow rt-repeat="obj in objects"/>
</tbody>

numrows가 배열이면 매우 간단합니다.

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

React의 배열 데이터 유형은 매우 우수하며 배열은 새 배열을 지원하고 필터를 지원하고 축소합니다.


이를 수행하는 방법에는 여러 가지가 있습니다. JSX는 결국 자바 스크립트로 컴파일되므로 유효한 자바 스크립트를 작성하는 한 괜찮을 것입니다.

내 대답은 이미 여기에 제시된 모든 멋진 방법을 통합하는 것입니다.

객체 배열이없는 경우 단순히 행 수 :

return블록 내에서 다음을 만들고 Array사용합니다 Array.prototype.map.

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

return블록 외부에서 일반 JavaScript for 루프를 사용하면됩니다.

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 루프를 사용하면됩니다.

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>
      {(() => {
        const rows = [];
        for (let i = 0; i < objectRows.length; i++) {
          rows.push(<ObjectRow key={i} data={objectRows[i]} />);
        }
        return rows;
      })()}
    </tbody>
  );
}

map진술 사용에 대한 몇 가지 답변이 있습니다 . 여기 내 반복자하여 완전한 예이다 FeatureList 리스트에 요소 기능 라는 JSON 데이터 구조에 기초하여 구성 요소 기능 .

const FeatureList = ({ features, onClickFeature, onClickLikes }) => (
  <div className="feature-list">
    {features.map(feature =>
      <Feature
        key={feature.id}
        {...feature}
        onClickFeature={() => onClickFeature(feature.id)}
        onClickLikes={() => onClickLikes(feature.id)}
      />
    )}
  </div>
); 

GitHub 에서 전체 FeatureList 코드볼 수 있습니다 . 기능의 비품은 여기에 나열됩니다 .


귀하의 주에 일련의 항목이 있다고 가정하겠습니다.

[{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>

... 또는 객체 배열을 준비하고 원하는 출력을 갖도록 함수에 매핑 할 수도 있습니다. 렌더 반환 내부에 로직이없는 코딩의 모범 사례를 유지하는 데 도움이되기 때문에 이것을 선호합니다.

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>
  )
}

간단히 사용 .map()하여 컬렉션을 <ObjectRow>반복하고 각 반복에서 소품과 함께 항목을 반환 합니다.

objects어딘가에 배열 이라고 가정합니다 ...

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

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>

이것을 render 메서드 return () 안에서 변환하기로했다면 가장 쉬운 방법은 map () 메서드를 사용하는 것 입니다. 아래와 같이 map () 함수를 사용하여 배열을 JSX 구문으로 매핑합니다 ( ES6 구문이 사용됨 ).


내부 부모 구성 요소 :

<tbody>
   { objectArray.map((object, index) => <ObjectRow key={index} object={object}>) }
</tbody>

key하위 구성 요소에 추가 속성에 유의하십시오 . 키 속성을 제공하지 않은 경우 콘솔에서 다음 경고를 볼 수 있습니다.

경고 : 배열 또는 반복기의 각 하위에는 고유 한 "키"소품이 있어야합니다.


이제 ObjectRow 구성 요소 에서 해당 속성의 개체에 액세스 할 수 있습니다.

ObjectRow 구성 요소 내부

const { object } = this.props

또는

const object = this.props.object

이것은 부모 구성 요소 object에서 ObjectRow 구성 요소 의 변수 전달한 개체를 가져와야 합니다. 이제 목적에 따라 해당 개체의 값을 뱉어 낼 수 있습니다.


참고 문헌 :

Javascript의 map () 메서드

ECMA Script 6 또는 ES6


나는 이것을 사용한다 :

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

PD : 열쇠를 잊지 마십시오. 그렇지 않으면 경고가 많이납니다!


나는 프로그래밍 논리가의 반환 값 외부에서 발생하는 접근 방식을 선호하는 경향이 render있습니다. 이렇게하면 실제로 렌더링 된 것을 쉽게 찾을 수 있습니다.

그래서 아마도 다음과 같은 일을 할 것입니다.

import _ from 'lodash';

...

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

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

분명히 이것은 인라인이 잘 작동 할 수있는 작은 양의 코드입니다.


물론 다른 답변에서 제안한 것처럼 .map으로 해결할 수 있습니다. 이미 babel을 사용하고 있다면 jsx-control-statements 사용에 대해 생각할 수 있습니다 . 약간의 설정이 필요하지만 가독성 측면에서는 가치가 있다고 생각합니다 (특히 비 반응 개발자의 경우). linter를 사용하는 경우 eslint-plugin-jsx-control-statements도 있습니다.


JSX 코드는 순수한 JavaScript 코드로 컴파일되며 모든 태그는 ReactElement객체 로 대체됩니다 . JavaScript에서는 반환 된 변수를 수집하기 위해 함수를 여러 번 호출 할 수 없습니다.

그것은 불법이며, 유일한 방법은 배열을 사용하여 함수 반환 변수를 저장하는 것입니다.

또는 이 상황을 처리하기 위해 JavaScript ES5 이후Array.prototype.map 로 사용 가능한 것을 사용할 수 있습니다.

Angularng-repeat 와 같은 반복 함수를 구현하기 위해 새로운 JSX 구문을 다시 생성하는 다른 컴파일러를 작성할 수 있습니다 .


여러 번 반복하고 반환하려면 frommap다음을 사용하여 수행 할 수 있습니다 .

<tbody>
  {
    Array.from(Array(i)).map(() => <ObjectRow />)
  }
</tbody>

어디 i = number of times


ES2015 Array.from with the map function + key

아무것도 없다면 요소를 반복하기 위해 함수 와 함께 .map()사용할 수 있습니다 .Array.from()map

<tbody>
  {Array.from({ length: 5 }, (value, key) => <ObjectRow key={key} />)}
</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>
        )
    

    방법 2

       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>
    )
    

JSX 코드 내에서 Javascript 구문을 작성하고 있으므로 Javascript를 중괄호로 묶어야합니다.

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

다음은 React 문서의 샘플입니다. JavaScript Expressions as Children

function Item(props) {
  return <li>{props.message}</li>;
}

function TodoList() {
  const todos = ['finish doc', 'submit pr', 'nag dan to review'];
  return (
    <ul>
      {todos.map((message) => <Item key={message} message={message} />)}
    </ul>
  );
}

귀하의 경우 다음과 같이 작성하는 것이 좋습니다.

function render() {
  return (
    <tbody>
      {numrows.map((roe, index) => <ObjectRow key={index} />)}
    </tbody>
  );
}

React는 배열의 데이터를 다르게하기 위해 Key를 사용하기 때문에 Key는 매우 중요합니다.


여기에 간단한 해결책이 있습니다.

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

매핑 및 복잡한 코드가 필요하지 않습니다. 행을 배열로 푸시하고 값을 반환하여 렌더링하면됩니다.


나는 그것을 사용한다

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

좋은 질문입니다.

특정 개수의 구성 요소를 추가하고 싶을 때하는 일은 도우미 기능을 사용하는 것입니다.

JSX를 반환하는 함수를 정의합니다.

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

//... in JSX

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

자체 호출 함수를 사용할 수도 있습니다.

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

           })()}
        </tbody>

다음과 같이 할 수 있습니다.

let foo = [1,undefined,3]
{ foo.map(e => !!e ? <Object /> : null )}

참고 URL : https://stackoverflow.com/questions/22876978/loop-inside-react-jsx

반응형