map 및 join을 사용하여 반응 구성 요소를 렌더링하는 방법


102

String Array를 표시 할 구성 요소가 하나 있습니다. 코드는 다음과 같습니다.

React.createClass({
  render() {
     <div>
        this.props.data.map(t => <span>t</span>)
     </div>
  }
})

완벽하게 잘 작동합니다. ie if props.data = [ 'tom', 'jason', 'chris'] 페이지에서 렌더링 된 결과는 tomjasonchris입니다.

그런 다음 쉼표를 사용하여 모든 이름을 결합하고 싶으므로 코드를 다음과 같이 변경합니다.

this.props.data.map(t => <span>t</span>).join(', ')

그러나 렌더링 된 결과는 [Object], [Object], [Object]입니다.

렌더링 할 반응 구성 요소가되도록 객체를 해석하는 방법을 모르겠습니다. 어떠한 제안 ?

답변:


147

간단한 해결책은 reduce()두 번째 인수없이 이전 결과를 퍼 뜨리지 않고 사용 하는 것입니다.

class List extends React.Component {
  render() {
     <div>
        {this.props.data
          .map(t => <span>{t}</span>)
          .reduce((prev, curr) => [prev, ', ', curr])}
     </div>
  }
}

두 번째 인수없이 reduce()인덱스 1에서 시작 하는 대신 0, 중첩 된 배열을 완벽하게 행복하다 반응한다.

주석에서 말했듯이 reduce()두 번째 인수가 없으면 빈 배열이 발생 하기 때문에 하나 이상의 항목이있는 배열에만 이것을 사용하고 싶습니다 . 어쨌든 빈 배열에 대해 'this is empty'와 같은 사용자 지정 메시지를 표시하고 싶기 때문에 일반적으로 이것은 문제가되지 않습니다.

Typescript 업데이트

type-unsafe없이 Typescript any에서 React.ReactNode유형 매개 변수를 사용하여 사용할 수 있습니다 .map().

class List extends React.Component {
  render() {
     <div>
        {this.props.data
          .map<React.ReactNode>(t => <span>{t}</span>)
          .reduce((prev, curr) => [prev, ', ', curr])}
     </div>
  }
}

3
If the array is empty and no initialValue was provided, TypeError would be thrown.. 그래서 빈 배열에서는 작동하지 않습니다.
Eugene Krevenets 2016

6
또한 이것은 prev배열을 재귀 적으로 중첩합니다 . 예를 들면 [1, 2, 3, 4]됩니다 [[[1,",",2],",",3],",",4].
Tamlyn

2
@ Tamlyn : 답변에서 귀하의 요점에 대한 원래 언급 ( 'React는 중첩 배열에 완벽하게 만족합니다')이 충분히 명확하다고 생각합니까? 아니면 이것에 대해 자세히 설명해야합니까?
Maarten ter Horst

1
누구든지이 솔루션을 React + TypeScript로 만들었습니까?
Matt Dell

1
@Jstuff 나는 무엇이든 사용해야합니다. .reduce((prev: JSX.Element, current: JSX.Element): any => [prev, (<span>&nbsp;</span>), current])
Matt Dell

26

reduce배열의 여러 요소를 결합하는 데 사용할 수 있습니다 .

React.createClass({
  render() {
     <div>
        this.props.data
        .map(t => <span>t</span>)
        .reduce((accu, elem) => {
            return accu === null ? [elem] : [...accu, ',', elem]
        }, null)
     </div>
  }
})

이것은 누산기를 null로 초기화하므로 배열의 첫 번째 항목을 래핑 할 수 있습니다. 배열의 다음 각 요소에 대해를 사용하여 이전 요소를 모두 포함하는 새 배열을 생성 ...-operator하고 구분 기호를 추가 한 다음 다음 요소를 추가합니다.

Array.prototype.reduce ()


2
고마워요, 정확히 제가 필요한 것입니다. 누산기를 빈 배열로 초기화하여 null 검사와 삼항을 제거 할 수 있습니다
Larry

7
@Larry null 검사와 삼항을 제거하고 []를 초기화 프로그램으로 전달하면 선행 쉼표를 어떻게 피할 수 있습니까? ['a'].reduce((a, e) => [...a, ',', e],[])수익률 [",", "a"]. 이니셜 라이저를 전달하지 않으면 배열이 비어 있지 않으면 TypeError가 반환됩니다.
가이

@Guy 당신은 절대적으로 정확합니다-내 오류는 내가 값을 공백으로 결합하고 렌더링 된 출력에서 ​​빈 범위를 누락했다는 것입니다
Larry

12

React 16으로 업데이트 : 이제 문자열을 직접 렌더링 할 수 있으므로 쓸모없는 <span>태그를 모두 제거하여 코드를 단순화 할 수 있습니다 .

const list = ({ data }) => data.reduce((prev, curr) => [ prev, ', ', curr ]);

8

허용되는 답변은 실제로 배열 배열을 반환합니다. prev 매번 . React는이 작업을 수행 할 수있을만큼 똑똑하지만 맵의 각 결과에 키를 부여 할 때 Reacts diffing 알고리즘을 깨는 등 향후 문제를 일으키는 경향이 있습니다.

새로운 React.Fragment기능을 통해 근본적인 문제없이 이해하기 쉬운 방식으로이를 수행 할 수 있습니다.

class List extends React.Component {
  render() {
     <div>
        {this.props.data
          .map((t, index) => 
            <React.Fragment key={index}>
              <span> {t}</span> ,
            </React.Fragment>
          )
      </div>
  }
}

함께 React.Fragment우리는 간단하게 분리 배치 할 수 있습니다 ,반환 된 HTML의 외부 불평하지 않습니다 반응한다.


2
최고 솔루션,하지만 당신은 배열의 마지막 요소에 쉼표를 제거해야
indapublic

이를 해결하기 위해 항상 터너 리와 색인을 사용할 수 있습니다.
Jstuff dec

2
이 수정으로 마지막 쉼표를 제거 할 수 있습니다. <React.Fragment key = {index}> <span> {t} </ span> {index === this.props.data.length-1? '': ','} </React.Fragment>
JohnP

7

<span>{t}</span>당신이 반환하는 객체가 아닌 문자열입니다. 그것에 대한 반응 문서를 확인하십시오 https://facebook.github.io/react/docs/jsx-in-depth.html#the-transform

.join()에서 반환 된 배열을 사용 map하면 객체 배열을 결합하게됩니다.[object Object], ...

안에 쉼표를 넣어 <span></span>원하는 방식으로 렌더링 할 수 있습니다.

  render() {
    return (
      <div>
        { this.props.data.map(
            (t,i) => <span>{t}{ this.props.data.length - 1 === i ? '' : ','} </span>
          )
        }
      </div>
    )
  }

샘플 : https://jsbin.com/xomopahalo/edit?html,js,output


3

내 변형 :

{this.props.data
    .map(item => <span>{item}</span>)
    .map((item, index) => [index > 0 && ', ', item ])}

2

쉼표로 구분 된 구성 요소 배열을 렌더링하려는 경우 일반적으로 reduce너무 장황합니다. 이러한 경우 더 짧은 해결책은 다음과 같습니다.

{arr.map((item, index) => (
  <Fragment key={item.id}>
    {index > 0 && ', '}
    <Item {...item} />
  </Fragment>
))}

{index > 0 && ', '} 첫 번째 항목을 제외한 모든 배열 항목 앞에 쉼표와 공백을 렌더링합니다.

마지막에서 두 번째 항목과 마지막 항목을 다른 것으로 분리하려면 문자열이라고 말하면 다음 과 같이 ' and '바꿀 수 있습니다.{index > 0 && ', '}

{index > 0 && index !== arr.length - 1 && ', '}
{index === arr.length - 1 && ' and '}

2

es6를 사용하면 다음과 같이 할 수 있습니다.

const joinComponents = (accumulator, current) => [
  ...accumulator, 
  accumulator.length ? ', ' : '', 
  current
]

그리고 실행 :

listComponents
  .map(item => <span key={item.id}> {item.t} </span>)
  .reduce(joinComponents, [])

1

","를 외부에 유지하려면 중첩 배열을 사용하십시오.

  <div>
      {this.props.data.map((element, index) => index == this.props.data.length - 1 ? <span key={index}>{element}</span> : [<span key={index}>{element}</span>, ", "])}
  </div>

항상 마지막 요소인지 확인하는 대신 배열에 데이터를 저장하고 마지막 요소를 수정하여 최적화하십시오.

  let processedData = this.props.data.map((element, index) => [<span key={index}>{element}</span>, ", "])
  processedData [this.props.data.length - 1].pop()
  <div>
      {processedData}
  </div>

0

이것은 나를 위해 일했습니다.

    {data.map( ( item, i ) => {
                  return (
                      <span key={i}>{item.propery}</span>
                    )
                  } ).reduce( ( prev, curr ) => [ prev, ', ', curr ] )}

0

Pith 에서 언급했듯이 React 16에서는 문자열을 직접 사용할 수 있으므로 더 이상 span 태그로 문자열을 래핑 할 필요가 없습니다. 바탕 마틴의 대답 당신은 또한 바로 사용자 정의 메시지를 처리 할 경우, (그리고 피할가 빈 배열에 오류를 throw), 당신이 원과 작업을 이끌 수 있다면 어레이의 길이 속성에 문. 다음과 같이 보일 수 있습니다.

class List extends React.Component {
  const { data } = this.props;

  render() {
     <div>
        {data.length
          ? data.reduce((prev, curr) => [prev, ', ', curr])
          : 'No data in the array'
        }
     </div>
  }
}

0

플랫 배열을 반환해야합니다. 초기 빈 배열을 제공하여 반복 불가능한 첫 번째 객체로 s 케이스를 처리하고 결과에서 필요하지 않은 첫 번째 쉼표를 필터링합니다.

[{}, 'b', 'c'].reduce((prev, curr) => [...prev, ', ', curr], []).splice(1) // => [{}, 'b', 'c']

0

여기 답변에 불필요한 확산과 중첩이 많이 있다고 생각하는 사람은 나뿐입니까? 간결하다는 점은 확실하지만, 중첩 된 배열 / 조각을 처리하는 방법을 변경하는 규모 또는 React 문제에 대한 문을 열어 둡니다.

const joinJsxArray = (arr, joinWith) => {
  if (!arr || arr.length < 2) { return arr; }

  const out = [arr[0]];
  for (let i = 1; i < arr.length; i += 1) {
    out.push(joinWith, arr[i]);
  }
  return out;
};

// render()
<div>
  {joinJsxArray(this.props.data.map(t => <span>t</span>), ', ')}
</div>

하나의 배열, 중첩 없음. 섹시한 메소드 체인도 없지만이 작업을 자주 수행하는 경우 항상 배열 프로토 타입에 추가하거나 매핑 콜백을받는 함수로 래핑하여 한 번에 모두 수행 할 수 있습니다.


0
function YourComponent(props) {

  const criteria = [];

  if (something) {
    criteria.push(<strong>{ something }</strong>);
  }

  // join the jsx elements with `, `
  const elements = criteria.reduce((accu, elem) => {
    return accu === null ? [elem] : [...accu, ', ', elem]
  }, null);

  // render in a jsx friendly way
  return elements.map((el, index) => <React.Fragment key={ index }>{ el }</React.Fragment> );

}
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.