Facebook React의 JSX로 조건부 요소를 사용하고 DRY를 유지하는 방법은 무엇입니까?


229

JSX에 요소를 선택적으로 포함 시키려면 어떻게해야합니까? 다음은 컴포넌트가 전달 된 경우 컴포넌트에 있어야하는 배너를 사용하는 예제입니다. 피하고 ​​싶은 것은 if 문에서 HTML 태그를 복제해야합니다.

render: function () {
    var banner;
    if (this.state.banner) {
        banner = <div id="banner">{this.state.banner}</div>;
    } else {
        banner = ?????
    }
    return (
        <div id="page">
            {banner}
            <div id="other-content">
                blah blah blah...
            </div>
        </div>
    );
}

3
else지점 이 없으면 어떻게 작동합니까? 저는 jsx에 익숙하지 않습니다 ...
Tom Fenech


옵션의 완전한 목록은 반작용 조건부 렌더링을 할 : robinwieruch.de/conditional-rendering-react
로빈 Wieruch

답변:


151

배너를 정의되지 않은 상태로두면 포함되지 않습니다.


1
나는 그 대답 옆에 쓰레기 외에는 아무것도 생각할 수 없다 ... 마치 신들을 우연히 발견 한 것처럼
Timmerz

null뿐만 아니라 작동 합니까 undefined? 또한 사양의 일부가 이런 식으로 작동하므로 향후에는 깨지지 않을까요?
hippietrail

133

이건 어때? 간단한 도움 If컴포넌트를 정의 해 봅시다 .

var If = React.createClass({
    render: function() {
        if (this.props.test) {
            return this.props.children;
        }
        else {
            return false;
        }
    }
});

그리고 이런 식으로 사용하십시오 :

render: function () {
    return (
        <div id="page">
            <If test={this.state.banner}>
                <div id="banner">{this.state.banner}</div>
            </If>
            <div id="other-content">
                blah blah blah...
            </div>
        </div>
    );
}

업데이트 : 내 대답이 대중화 되면서이 솔루션과 관련된 가장 큰 위험에 대해 경고해야한다고 생각합니다. 다른 답변에서 지적했듯이 <If />구성 요소 내부의 코드 는 조건이 true인지 false인지에 관계없이 항상 실행됩니다. 따라서 다음 예제banneris 인 경우 실패 null합니다 (두 번째 줄의 속성 액세스 참고).

<If test={this.state.banner}>
    <div id="banner">{this.state.banner.url}</div>
</If>

사용할 때주의해야합니다. 대안 (safer) 접근법에 대한 다른 답변을 읽는 것이 좋습니다.

업데이트 2 : 이 접근법은 위험 할뿐만 아니라 필사적으로 번거 롭습니다. 개발자 (me)가 패턴을 전달하려고 할 때 한 영역에서 다른 영역으로 접근하려고 시도하지만 실제로 작동하지 않습니다 (이 경우 다른 템플릿 언어)의 전형적인 예입니다.

조건부 요소가 필요한 경우 다음과 같이하십시오.

render: function () {
    return (
        <div id="page">
            {this.state.banner &&
                <div id="banner">{this.state.banner}</div>}
            <div id="other-content">
                blah blah blah...
            </div>
        </div>
    );
}

else 브랜치가 필요한 경우 삼항 연산자를 사용하십시오.

{this.state.banner ?
   <div id="banner">{this.state.banner}</div> :
   <div>There is no banner!</div>
}

더 짧고 우아하며 안전합니다. 나는 항상 그것을 사용합니다. 유일한 단점은 else if쉽게 분기 할 수는 없지만 일반적으로 그렇게하지는 않는다는 것입니다.

어쨌든 이것은 JavaScript의 논리 연산자 가 작동 하는 방식 덕분에 가능 합니다. 논리 연산자는 다음과 같은 작은 트릭을 허용합니다.

<h3>{this.state.banner.title || 'Default banner title'}</h3>

1
감사. 나는이 github.com/facebook/react/issues/690을 읽는 것이 좋습니다. 이 링크는이 질문에 대한 의견에 게시되었으며 솔루션을 게시 한 후에 알았습니다. 당신이 그것을 확인하면, 어떤 사람은이 솔루션을 언급하지만 권장하지는 않습니다. 개인적으로 적어도 OP의 경우에는 괜찮다고 생각하지만이 방법이 완벽하지 않다는 것은 사실입니다 (예 : 다른 분기를 정의하는 좋은 방법은 없습니다). 어쨌든 읽을 가치가 있습니다.
tobik

1
이것이 최신 버전으로 여전히 작동하는지 확실하지 않은 경우 반환 된 값이ReactElement
srph

다른 요소 <span>또는로 감싸십시오 <div>.
tobik

<noscript>가 <tr>의 하위 항목으로 허용되지 않기 때문에 이것을 사용하여 <td>를 렌더링하거나 <table>에서 비어있는 경우 문제가 있습니다. 그렇지 않으면 그것은 나를 위해 잘 작동합니다.
Green Su

1
이 작업을 수행하려는 경우 꽤 훌륭한 변환 방법이 있습니다 : npmjs.com/package/jsx-control-statements
steve

82

개인적으로, ( JSX In Depth )에 표시되는 삼항식 이 ReactJs 표준을 따르는 가장 자연스러운 방법이라고 생각합니다.

다음 예를 참조하십시오. 첫눈에 약간 지저분하지만 잘 작동합니다.

<div id="page">
  {this.state.banner ? (
    <div id="banner">
     <div class="another-div">
       {this.state.banner}
     </div>
    </div>
  ) : 
  null} 
  <div id="other-content">
    blah blah blah...
  </div>
</div>

참고 : 대괄호는 구성 요소 리턴과 동일하므로 컨텐츠는 <div> </ div>로 묶어야합니다.
JoeTidee 1

@Chiedo 왜 인기있는 답변을 선호합니까? 이것은 잘 작동하는 것 같습니다.
눈사람

2
@ moby 나는 대중적인 대답이 더 역동적이며 더 깨끗한 렌더링 기능을 초래한다고 생각합니다. 이 방법을 사용하면 조건이 여러 개인 경우 어떻게됩니까? 이제이 이상한 형식으로 중첩의 광기가 생겼으며 조건에 따라 두 개의 별도 영역에서 동일한 변경이 필요한 경우 조건을 다시 작성해야합니다. 그래도 내 의견! :)
Chiedo 2016

관련 페이지도 상당히 유용합니다 : facebook.github.io/react/docs/…
Neil

46

당신은 또한 그것을 쓸 수 있습니다

{ this.state.banner && <div>{...}</div> }

당신이 경우 state.banner이다 null하거나 undefined, 조건의 오른쪽 건너 뜁니다.


41

If코드 블록이 있기 때문에 스타일의 구성 요소는 위험 항상 실행 에 관계없이 상태. 예를 들어 다음과 같은 경우 null 예외 banner가 발생합니다 null.

//dangerous
render: function () {
  return (
    <div id="page">
      <If test={this.state.banner}>
        <img src={this.state.banner.src} />
      </If>
      <div id="other-content">
         blah blah blah...
      </div>
    </div>
  );
}

또 다른 옵션은 인라인 함수를 사용하는 것입니다 (특히 else 문에 유용).

render: function () {
  return (
    <div id="page">
      {function(){
        if (this.state.banner) {
          return <div id="banner">{this.state.banner}</div>
        }
      }.call(this)}
      <div id="other-content">
         blah blah blah...
      </div>
    </div>
  );
}

반응 문제의 또 다른 옵션 :

render: function () {
  return (
    <div id="page">
      { this.state.banner &&
        <div id="banner">{this.state.banner}</div>
      }
      <div id="other-content">
         blah blah blah...
      </div>
    </div>
  );
}

2
지금까지의 모든 솔루션 중에서 인라인 기능이 가장 우아하고 간단 해 보입니다. 조심해야 할 것이 있습니까?
suryasankar

22

&& + 코드 스타일 + 작은 구성 요소

이 간단한 테스트 구문 + 코드 스타일 규칙 + 작은 집중 구성 요소는 나에게 가장 읽기 쉬운 옵션입니다. false, 0또는 과 같은 허위 값에 특별한주의를 기울여야합니다 "".

render: function() {
    var person= ...; 
    var counter= ...; 
    return (
       <div className="component">
          {person && (
            <Person person={person}/>
          )}
          {(typeof counter !== 'undefined') && (
            <Counter value={counter}/>
          )}
       </div>
    );
}

표기법

ES7 stage-0 do 표기법 구문도 매우 좋으며 IDE가 올바르게 지원할 때 확실히 사용할 것입니다.

const Users = ({users}) => (
  <div>
    {users.map(user =>
      <User key={user.id} user={user}/>
    )}
  </div>
)  

const UserList = ({users}) => do {
  if (!users) <div>Loading</div>
  else if (!users.length) <div>Empty</div>
  else <Users users={users}/>
}

자세한 내용은 여기에 있습니다 : ReactJs- "If"컴포넌트 만들기 ... 좋은 생각입니까?


기본 정보가 아닌 무료 정보 : 첫 번째 정보short-circuit syntax
sospedra

1
@Deerloper &&와 &의 차이점은 컴퓨터 학교에서 가장 먼저 배우는 것 중 하나이지만 일부 사람들은 알지 못할 수도 있으므로 자세한 설명을 제공하는 것은 나쁜 생각이 아닙니다. en.wikipedia.org/wiki/Short-circuit_evaluation
Sebastien Lorber

그러나 그들은 고전적인 조건 문의 일부로 그것을 가르칩니다. 단락을 사용하여 React 구성 요소를 렌더링하는 것에 대해 많은 사람들이 혼란스러워했습니다.)
sospedra

22

간단하고 함수를 만듭니다.

renderBanner: function() {
  if (!this.state.banner) return;
  return (
    <div id="banner">{this.state.banner}</div>
  );
},

render: function () {
  return (
    <div id="page">
      {this.renderBanner()}
      <div id="other-content">
        blah blah blah...
      </div>
    </div>
  );
}

이것은 내가 개인적으로 항상 따르는 패턴입니다. 코드를 정말 깨끗하고 이해하기 쉽게 만듭니다. Banner또한 너무 커지면 (또는 다른 장소에서 재사용 할 경우) 자체 구성 요소 로 리팩토링 할 수 있습니다 .



11

답변에서 이미 언급했듯이 JSX는 두 가지 옵션을 제공합니다.

  • 삼항 연산자

    { this.state.price ? <div>{this.state.price}</div> : null }

  • 논리적 연결

    { this.state.price && <div>{this.state.price}</div> }


그러나 그것들은 작동하지 않습니다 price == 0 .

JSX는 첫 번째 경우에 잘못된 분기를 렌더링하고 논리적으로 연결되는 경우 아무것도 렌더링되지 않습니다. 속성이 0 일 경우 JSX 외부의 if 문만 사용하십시오.


그것은 JSX 문제가 아닙니다. 일반 JS에서도 동일하게 작동하는 조건 자체입니다. 숫자를 원하면 typeof(this.state.price) === "number"조건으로 사용 하십시오 (둘 중 하나의 변형).
Kroltan

8

이 컴포넌트는 "if"분기 내에 둘 이상의 요소가있는 경우 작동합니다.

var Display = React.createClass({
  render: function () {
    if (!this.props.when) {
      return false;
    }
    return React.DOM.div(null, this.props.children);
  },
});

용법:

render: function() {
  return (
    <div>
      <Display when={this.state.loading}>
        Loading something...
        <div>Elem1</div>
        <div>Elem2</div>
      </Display>
      <Display when={!this.state.loading}>
        Loaded
        <div>Elem3</div>
        <div>Elem4</div>
      </Display>
    </div>
  );
}

Ps 누군가는 이러한 구성 요소가 코드 읽기에 좋지 않다고 생각합니다. 그러나 내 마음에 자바 스크립트가있는 HTML은 더 나쁩니다.


If answer here와 같이 표시되지 않더라도 여전히 잘못된 조건을 실행합니다.
키건 82

3

대부분의 예제에는 조건부로 렌더링되는 "html"한 줄이 있습니다. 조건부로 렌더링 해야하는 여러 줄이있을 때 이것은 읽을 수있는 것처럼 보입니다.

render: function() {
  // This will be renered only if showContent prop is true
  var content = 
    <div>
      <p>something here</p>
      <p>more here</p>
      <p>and more here</p>
    </div>;

  return (
    <div>
      <h1>Some title</h1>

      {this.props.showContent ? content : null}
    </div>
  );
}

첫 번째 예는 null조건부와 같은 다른 컨텐츠를 조건부로 렌더링 할 수 있기 때문에 좋습니다.{this.props.showContent ? content : otherContent}

그러나 컨텐츠를 표시하거나 숨기려면 부울, 널 및 정의되지 않음이 무시 되므로 훨씬 좋습니다.

render: function() {
  return (
    <div>
      <h1>Some title</h1>

      // This will be renered only if showContent prop is true
      {this.props.showContent &&
        <div>
          <p>something here</p>
          <p>more here</p>
          <p>and more here</p>
        </div>
      }
    </div>
  );
}

2

React의 구성 요소경우 다른 해결책이 있습니다 .

var Node = require('react-if-comp');
...
render: function() {
    return (
        <div id="page">
            <Node if={this.state.banner}
                  then={<div id="banner">{this.state.banner}</div>} />
            <div id="other-content">
                blah blah blah...
            </div>
        </div>
    );
}

2

보다 명시적인 바로 가기를 사용합니다. 즉석에서 호출 된 함수 식 (IIFE) :

{(() => {
  if (isEmpty(routine.queries)) {
    return <Grid devices={devices} routine={routine} configure={() => this.setState({configured: true})}/>
  } else if (this.state.configured) {
    return <DeviceList devices={devices} routine={routine} configure={() => this.setState({configured: false})}/>
  } else {
    return <Grid devices={devices} routine={routine} configure={() => this.setState({configured: true})}/>
  }
})()}


1

정말 깨끗한 한 줄 버전도 있습니다 ... {this.props.product.title || "제목 없음" }

즉 :

render: function() {
            return (
                <div className="title">
                    { this.props.product.title || "No Title" }
                </div>
            );
        }

위의 샘플에서 작동합니까? 배너 소품이없는 경우 배너 div가 나타나지 않아야하는 위치는 무엇입니까?
잭 앨런

1

술어가 통과하는 경우에만 요소를 안전하게 렌더링하기 위해 https://github.com/ajwhite/render-if 최근에 만들었습니다 .

{renderIf(1 + 1 === 2)(
  <span>Hello!</span>
)}

또는

const ifUniverseIsWorking = renderIf(1 + 1 === 2);

//...

{ifUniverseIsWorking(
  <span>Hello!</span>
)}

1

다음과 같이 삼항 연산자를 사용하여 조건부로 요소를 포함 할 수 있습니다.

render: function(){

         return <div id="page">

                  //conditional statement
                  {this.state.banner ? <div id="banner">{this.state.banner}</div> : null}

                  <div id="other-content">
                      blah blah blah...
                  </div>

               </div>
}

1

함수를 사용하여 구성 요소를 반환하고 렌더링 함수를 얇게 유지할 수 있습니다

class App extends React.Component {
  constructor (props) {
    super(props);
    this._renderAppBar = this._renderAppBar.bind(this);
  }

  render () {
    return <div>
      {_renderAppBar()}

      <div>Content</div>

    </div>
  }

  _renderAppBar () {
    if (this.state.renderAppBar) {
      return <AppBar />
    }
  }
}

1

다음은 ES6을 사용하는 접근법입니다.

import React, { Component } from 'react';
// you should use ReactDOM.render instad of React.renderComponent
import ReactDOM from 'react-dom';

class ToggleBox extends Component {
  constructor(props) {
    super(props);
    this.state = {
      // toggle box is closed initially
      opened: false,
    };
    // http://egorsmirnov.me/2015/08/16/react-and-es6-part3.html
    this.toggleBox = this.toggleBox.bind(this);
  }

  toggleBox() {
    // check if box is currently opened
    const { opened } = this.state;
    this.setState({
      // toggle value of `opened`
      opened: !opened,
    });
  }

  render() {
    const { title, children } = this.props;
    const { opened } = this.state;
    return (
      <div className="box">
        <div className="boxTitle" onClick={this.toggleBox}>
          {title}
        </div>
        {opened && children && (
          <div class="boxContent">
            {children}
          </div>
        )}
      </div>
    );
  }
}

ReactDOM.render((
  <ToggleBox title="Click me">
    <div>Some content</div>
  </ToggleBox>
), document.getElementById('app'));

데모 : http://jsfiddle.net/kb3gN/16688/

나는 다음과 같은 코드를 사용하고 있습니다 :

{opened && <SomeElement />}

사실 일 SomeElement경우에만 렌더링 됩니다 opened. JavaScript가 논리 조건을 해결하는 방식 때문에 작동합니다.

true && true && 2; // will output 2
true && false && 2; // will output false
true && 'some string'; // will output 'some string'
opened && <SomeElement />; // will output SomeElement if `opened` is true, will output false otherwise

React무시 하겠지만 false조건부로 일부 요소를 렌더링하는 매우 좋은 방법입니다.


1

어쩌면 그것은 질문을하는 누군가를 도울 수 있습니다 : React의 모든 조건부 렌더링 React의 조건부 렌더링에 대한 모든 다른 옵션에 대한 기사입니다.

어떤 조건부 렌더링을 사용해야하는지에 대한 주요 내용 :

** 다른 경우라면

  • 가장 기본적인 조건부 렌더링입니다
  • 초보자 친화적
  • null을 반환하여 렌더 메소드에서 조기에 옵트 아웃하려면 if

** 삼항 연산자

  • if-else 문에 사용하십시오
  • if-else보다 간결합니다.

** 논리 && 연산자

  • 삼항 연산의 한쪽이 null을 반환 할 때 사용하십시오.

** 스위치 케이스

  • 말 수가 많은
  • 자체 호출 기능으로 만 인라인 가능
  • 그것을 피하고 대신 열거 형을 사용하십시오.

** 열거 형

  • 다른 주를 매핑하기에 완벽한
  • 하나 이상의 조건을 매핑하기에 완벽한

** 다단계 / 중첩 조건부 렌더링

  • 가독성을 위해 피하십시오
  • 간단한 조건부 렌더링을 통해 구성 요소를 더 가벼운 구성 요소로 분할
  • HOC 사용

** HOC

  • 조건부 렌더링을 차단하는 데 사용
  • 구성 요소는 주요 목적에 집중할 수 있습니다

** 외부 템플릿 구성 요소

  • 그것들을 피하고 JSX와 JavaScript에 익숙해 지십시오

1

ES6을 사용하면 간단한 원 라이너로 할 수 있습니다

const If = ({children, show}) => show ? children : null

"show"는 부울이며이 클래스를 사용하여

<If show={true}> Will show </If>
<If show={false}> WON'T show </div> </If>

1
나쁜. 항상 계산됩니다.
Qwertiy

0

나는 이것이 언급되지 않았다고 생각합니다. 이것은 당신의 대답과 같지만 더 간단하다고 생각합니다. 항상 표현식에서 문자열을 리턴 할 수 있으며 표현식 내에 jsx를 중첩 할 수 있으므로 인라인 표현식을 쉽게 읽을 수 있습니다.

render: function () {
    return (
        <div id="page">
            {this.state.banner ? <div id="banner">{this.state.banner}</div> : ''}
            <div id="other-content">
                blah blah blah...
            </div>
        </div>
    );
}

<script src="http://dragon.ak.fbcdn.net/hphotos-ak-xpf1/t39.3284-6/10574688_1565081647062540_1607884640_n.js"></script>
<script src="http://dragon.ak.fbcdn.net/hphotos-ak-xpa1/t39.3284-6/10541015_309770302547476_509859315_n.js"></script>
<script type="text/jsx;harmony=true">void function() { "use strict";

var Hello = React.createClass({
  render: function() {
    return (
      <div id="page">
        {this.props.banner ? <div id="banner">{this.props.banner}</div> : ''}
        <div id="other-content">
          blah blah blah...
        </div>
      </div>
    );   
  }
});

var element = <div><Hello /><Hello banner="banner"/></div>;
React.render(element, document.body);

}()</script>


0

Immediately-Invoked Function Expressions ( IIFE) if-else이상 render callbacks및 의 명시 성을 좋아합니다 ternary operators.

render() {
  return (
    <div id="page">
      {(() => (
        const { banner } = this.state;
        if (banner) {
          return (
            <div id="banner">{banner}</div>
          );
        }
        // Default
        return (
          <div>???</div>
        );
      ))()}
      <div id="other-content">
        blah blah blah...
      </div>
    </div>
  );
}

IIFE구문에 익숙해 {expression}져야하며 일반적인 React 구문이 있습니다.

function() {

}()

그 안에는 괄호 안에 싸야합니다

(function() {

}())

0

구성 요소를 조건부 렌더링하기 위해 렌더링 소품 을 사용하는 기술도 있습니다 . 이점은 조건이 충족 될 때까지 렌더링이 평가되지 않아 nullundefined 값 에 대한 걱정이 없다는 것 입니다.

const Conditional = ({ condition, render }) => {
  if (condition) {
    return render();
  }
  return null;
};

class App extends React.Component {
  constructor() {
    super();
    this.state = { items: null }
  }

  componentWillMount() {
    setTimeout(() => { this.setState({ items: [1,2] }) }, 2000);
  }

  render() {
    return (
      <Conditional
        condition={!!this.state.items}
        render={() => (
          <div>
            {this.state.items.map(value => <p>{value}</p>)}
          </div>
        )}
      />
    )
  }
}

0

전달 된 조건이 가득 찬 경우에만 무언가를 렌더링해야하는 경우 다음 구문을 사용할 수 있습니다.

{ condition && what_to_render }

이 방식의 코드는 다음과 같습니다.

render() {
    const { banner } = this.state;
    return (
        <div id="page">
            { banner && <div id="banner">{banner}</div> }
            <div id="other-content">
                blah blah blah...
            </div>
        </div>
    );
}

물론이를 수행 할 수있는 다른 유효한 방법이 있습니다. 그것은 모두 선호와 관할에 달려 있습니다. 관심 있다면 이 기사 에서 React에서 조건부 렌더링을 수행하는 방법에 대한 더 많은 방법을 배울 수 있습니다 !


-1

다른 옵션을 추가하기 만하면-커피 스크립트를 좋아하거나 견딜 수 있다면 coffee-react를 사용하여 JSX를 작성할 수 있습니다.

render: ->
  <div className="container">
    {
      if something
        <h2>Coffeescript is magic!</h2>
      else
        <h2>Coffeescript sucks!</h2>
    }
  </div>  

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