etc./StackOverFlow

React JSX 내부 루프

청렴결백한 만능 재주꾼 2022. 2. 8. 08:37
반응형

질문자 :B Robster


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 are adding 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의 예제가 변환하는 것과 거의 똑같습니다. JSX가 어떻게 작동하는지 알아보려면 Babel REPL을 사용하십시오.


Sophie Alpert

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

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

Brigand

map() 대한 배열이 아직 없고 이를 인라인하려는 경우 소스 레이아웃이 @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 확산할 때는 그렇지 않은 것 같습니다. 이를 명확히 하기 위해 문서 문제가 열려 있습니다. 그러나 귀하의 책임하에 사용하거나 폴리필을 사용하십시오.

바닐라 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() 대한 인수를 실제로 생략할 수 있다고 생각합니다 fill() 솔루션의 이전 버전에서 내 실수를 수정해 준 @FakeRainBrigand에게 감사드립니다(개정판 참조).

key

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


JMM

ES6 구문과 함께 map Array 메서드를 사용하기만 하면 됩니다.

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

key 속성을 잊지 마십시오.


danielfeelfine

Array 맵 기능을 사용하는 것은 요소의 배열 을 반복하고 React 에서 이에 따라 구성 요소를 만드는 매우 일반적인 방법입니다. 이것은 매우 효율적이고 JSX 에서 루프를 수행하는 깔끔한 방법인 루프를 수행하는 좋은 방법입니다. 그것은 그것을 할 수있는 유일한 방법은,하지만 좋은 방법이 아니다.

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

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

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

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

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

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

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


Alireza

이미 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}>repeated 3 times</li> ))} </ol> </div> ); } }

mpen

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

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

Brandon Sibeitokgong

몇 가지 지시문(예: rt-repeat)과 함께 React에서 JSX 스타일 템플릿을 사용할 수 있게 해주는 React Templates 를 확인하고 싶을 수도 있습니다.

반응 템플릿을 사용한 경우의 예는 다음과 같습니다.

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

Etai

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

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

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

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 블록 내에서 각 객체를 <ObjectRow> 구성 요소에 .map()

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

Yangshun Tay

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

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

React의 배열 데이터 유형이 훨씬 좋습니다. 어레이는 새 어레이를 지원하고 필터, 감소 등을 지원할 수 있습니다.


lulin

map 문 사용을 가리키는 몇 가지 답변이 있습니다. 다음은 FeatureList 구성 요소 내에서 반복기를 사용하여 features 라는 JSON 데이터 구조를 기반으로 Feature 구성 요소를 나열하는 완전한 예입니다.

 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 코드 를 볼 수 있습니다. 기능 고정 장치가 여기에 나열됩니다 .


Manav Sehgal

여러 번 반복하고 반환하려면 frommap 사용하여 이를 달성할 수 있습니다.

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

여기서 i = number of times


렌더링된 구성 요소에 고유 키 ID를 할당 하려면 React 문서 에서 제안한 대로 React.Children.toArray

React.Children.toArray

자식 불투명 데이터 구조를 각 자식에 할당된 키가 있는 평면 배열로 반환합니다. 렌더링 메서드에서 자식 컬렉션을 조작하려는 경우, 특히 this.props.children을 전달하기 전에 재정렬하거나 슬라이스하려는 경우에 유용합니다.

메모:

React.Children.toArray() 는 자식 목록을 병합할 때 중첩 배열의 의미를 보존하기 위해 키를 변경합니다. 즉, toArray는 반환된 배열의 각 키에 접두사를 붙여 각 요소의 키 범위가 해당 키를 포함하는 입력 배열로 지정됩니다.

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

Jee Mok

귀하의 주에 항목 배열이 있다고 가정해 보겠습니다.

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

JFAP

이것을 render 메소드의 return() 내부에서 변환하기로 선택한 경우 가장 쉬운 옵션은 map( ) 메소드를 사용하는 것입니다. 아래와 같이 map() 함수를 사용하여 배열을 JSX 구문으로 매핑합니다( ES6 구문이 사용됨 ).


상위 구성 요소 내부 :

 <tbody> { objectArray.map(object => <ObjectRow key={object.id} object={object.value}>) } </tbody>

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

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

참고: 사람들이 흔히 하는 실수 중 하나는 반복할 때 index index 를 키로 사용하는 것은 반패턴이며 여기에서 자세히 읽을 수 있습니다. 이 정적 목록이 아니라면 즉, 사용하지 않을 index 키로.


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

ObjectRow 구성 요소 내부

 const { object } = this.props

또는

 const object = this.props.object

이것은 부모 구성 요소에서 ObjectRow 구성 요소 object 이제 목적에 따라 해당 개체의 값을 뱉어낼 수 있습니다.


참조:

자바스크립트의 map() 메소드

ECMAScript 6 또는 ES6


bharadhwaj

ECMAScript 2015/ Babel 가능성은 JSX 배열을 생성하기 위해 생성기 함수를 사용하고 있습니다:

 function* jsxLoop(times, callback) { for(var i = 0; i < times; ++i) yield callback(i); } ... <tbody> {[...jsxLoop(numrows, i => <ObjectRow key={i}/> )]} </tbody>

David Q Hogan

지도 기능 + 키가 있는 ES2015 Array.from

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

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

Do Async

나는 이것을 사용한다:

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

추신: 키를 잊지 마십시오. 그렇지 않으면 많은 경고가 표시됩니다!


J C

...또는 객체 배열을 준비하고 함수에 매핑하여 원하는 출력을 얻을 수도 있습니다. 렌더 반환 내부에 논리가 없는 좋은 코딩 방법을 유지하는 데 도움이 되기 때문에 이 방법을 선호합니다.

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

Rafi Ud Daula Refat

단순히 .map() 을 사용하여 컬렉션을 반복하고 각 반복의 소품과 함께 <ObjectRow>

objects 가 어딘가에 배열이라고 가정하면 ...

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

Joshua Michael Calafell

이것은 여러 가지 방법으로 수행할 수 있습니다.

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

abhirathore2006

render 의 반환 값 밖에서 일어나는 접근 방식을 선호하는 경향이 있습니다. 이것은 실제로 grok에 쉽게 렌더링되는 것을 유지하는 데 도움이 됩니다.

그래서 나는 아마도 다음과 같이 할 것입니다.

 import _ from 'lodash'; ... const TableBody = ({ objects }) => { const objectRows = objects.map(obj => <ObjectRow object={obj} />); return <tbody>{objectRows}</tbody>; }

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


Adam Donahue

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

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

또는 JavaScript ES5부터 사용 가능한 Array.prototype.map 을 사용하여 이 상황을 처리할 수 있습니다.

Angular의 ng-repeat 처럼 반복 기능을 구현하기 위해 새로운 JSX 구문을 재생성하는 다른 컴파일러를 작성할 수도 있습니다.


hlissnake

물론 다른 답변에서 제안한 대로 .map으로 해결할 수 있습니다. 이미 Babel을 사용하고 있다면 jsx-control-statements 사용에 대해 생각할 수 있습니다.

약간의 설정이 필요하지만 가독성 측면에서(특히 React가 아닌 개발자의 경우) 가치가 있다고 생각합니다. 린터를 사용하는 경우 eslint-plugin-jsx-control-statements도 있습니다.


Jurgo Boemo

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

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

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


Javasamurai

자체 호출 기능을 사용할 수도 있습니다.

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

Fba Shad

나는 그것을 사용한다

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

Sampath

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

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

Rohit Jindal

다음은 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는 배열의 데이터를 다르게 하기 위해 키 를 사용하기 때문에 키 가 매우 중요하다는 점에 유의하십시오.


Sinka Lee

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

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

Gize Carolina Bonilla Madrazo

시간이 지남에 따라 언어는 점점 더 성숙해지고 있으며 우리는 종종 이와 같은 일반적인 문제에 부딪힙니다. 문제는 Component를 'n'번 반복하는 것입니다.

 {[...new Array(n)].map((item, index) => <MyComponent key={index} />)}

여기서 n은 반복하려는 횟수입니다. item 은 정의되지 않고 index 는 평소와 같이 됩니다. 또한 ESLint 는 배열 인덱스를 키로 사용하는 것을 권장하지 않습니다.

for 루프를 피하기 전에 배열을 초기화할 필요가 없다는 장점이 있습니다...

item 을 undefined 로 사용하는 불편함을 피하기 위해 _ 사용하여 linting 시 무시되고 다음과 같은 linting 오류가 발생하지 않도록 할 수 있습니다.

 {[...new Array(n)].map((_, index) => <MyComponent key={index} />)}

pope_maverick

출처 : http:www.stackoverflow.com/questions/22876978/loop-inside-react-jsx

반응형