Как иметь условные элементы и оставаться сухим с JSX Facebook React?
как дополнительно включить элемент в JSX? Вот пример использования баннера, который должен быть в компоненте, если он был передан. Чего я хочу избежать, так это дублировать HTML-теги в операторе if.
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>
);
}
27 ответов
как насчет этого. Давайте определим простую помощь 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 />
компонент выполняется всегда, независимо от того, является ли условие истинным или ложным. Поэтому следующее пример будет сбой в случае banner
и null
(обратите внимание на отель на второй линии):
<If test={this.state.banner}>
<div id="banner">{this.state.banner.url}</div>
</If>
вы должны быть осторожны, когда вы используете его. Я предлагаю прочитать другие ответы для альтернативных (более безопасных) подходов.
обновление 2: оглядываясь назад, этот подход не только опасно, но и крайне обременительно. Это типичный пример того, когда разработчик (Я) пытается передать шаблоны и подходы, которые он знает из одной области в другую, но на самом деле это не так работа (в данном случае другие языки шаблонов).
Если вам нужен условный элемент, делай так:
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>
лично я действительно думаю, что троичные выражения показывают в http://facebook.github.io/react/tips/if-else-in-JSX.html самый естественный путь который соответствует с стандартами 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>
вы также можете написать его как
{ this.state.banner && <div>{...}</div> }
если state.banner
is null
или undefined
, пропущена правая сторона условия.
на If
компонент стиля опасен, потому что блок кода всегда исполняются независимо от состояния. Например, это вызовет исключение null, если banner
is 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>
);
}
еще один вариант от react вопросы:
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>
);
}
&& + код-стиль + небольшие компоненты
этот простой синтаксис теста + соглашение в стиле Кода + небольшие сфокусированные компоненты для меня самый читаемый вариант там. Вам просто нужно заботиться о фальшивых значениях, таких как 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 синтаксис нотации также очень хорош, и я окончательно использую его, когда моя 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}/>
}
просто создайте функцию.
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
в свой собственный компонент, если он становится слишком большим (или повторно используется в других местах).
экспериментальный ES7 do
синтаксис делает это легко. Если вы используете Babel, включите es7.doExpressions
функции после:
render() {
return (
<div id="banner">
{do {
if (this.state.banner) {
this.state.banner;
} else {
"Something else";
}
}}
</div>
);
}
см.http://wiki.ecmascript.org/doku.php?id=strawman:do_expressions
как уже упоминалось в ответах, JSX представляет вам два варианта
-
тернарный оператор
{ this.state.price ? <div>{this.state.price}</div> : null }
-
логическое
{ this.state.price && <div>{this.state.price}</div> }
однако, те не работают для price == 0
.
JSX будет отображать ложную ветвь в первом случае, и в случае логического соединения ничего не будет отображаться. Если свойство может быть 0, просто используйте операторы if вне вашего JSX.
этот компонент работает, когда у вас есть более одного элемента внутри ветви "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>
);
},
P. s. кто-то думает, что эти компоненты не подходят для чтения кода. Но на мой взгляд html с javascript хуже
большинство примеров имеют одну строку "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}
но если вам просто нужно показать / скрыть контент, это еще лучше, так как логические значения, Null и Undefined игнорируются
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>
);
}
есть другое решение,если компонент для 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>
);
}
Я использую более явный ярлык: немедленно вызываемое выражение функции (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})}/>
}
})()}
Я сделал https://www.npmjs.com/package/jsx-control-statements чтобы сделать его немного проще, в основном это позволяет определить <If>
условные обозначения в виде тегов, а затем компилирует их в троичные ifs, чтобы код внутри <If>
выполняется, только если условие истинно.
есть также очень чистый line версия... { этот.реквизит.товар.title / / "нет Title"}
Ie:
render: function() {
return (
<div className="title">
{ this.props.product.title || "No Title" }
</div>
);
}
Я сделал https://github.com/ajwhite/render-if недавно безопасно визуализировать элементы только если предикат передает.
{renderIf(1 + 1 === 2)(
<span>Hello!</span>
)}
или
const ifUniverseIsWorking = renderIf(1 + 1 === 2);
//...
{ifUniverseIsWorking(
<span>Hello!</span>
)}
вы можете условно включать элементы, используя тернарный оператор, например:
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>
}
вы можете использовать функцию и вернуть компонент и сохранить тонкую функцию рендеринга
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 />
}
}
}
вот мой подход с использованием 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
As React
игнорировать false
, Я считаю, что это очень хороший способ условно отобразить некоторые элементы.
может быть, это поможет кому-то, кто сталкивается с вопросом: все условные визуализации в React это статья обо всех различных вариантах условного рендеринга в React.
Key takeaways когда использовать, какой условный рендеринг:
* * if-else
- является самым основным условным рендерингом
- для начинающих
- используйте if для раннего отказа от метода рендеринга, вернувшись значение null
** тернарный оператор
- используйте его над оператором if-else
- это более лаконично, чем если-нибудь
** логический оператор&&
- используйте его, когда одна сторона троичной операции вернет null
** корпус переключателя
- подробное
- может быть встроен только с функцией самостоятельного вызова
- избегайте его, используйте перечисления вместо
** перечисления
- идеально подходит для отображения различных состояний
- идеально подходит для отображения более одного условия
* * многоуровневые / вложенные условные визуализации
- избегайте их ради удобочитаемости
- разделить компоненты на более легкие компоненты с их собственным простым условным рендерингом
- использовать HOCs
** HOCs
- используйте их для защиты от условного рендеринга
- компоненты могут сосредоточиться на своей основной цели
** внешние компоненты шаблонов
- избегайте их и будьте удобны с JSX и JavaScript
С ES6 вы можете сделать это с помощью простого однострочного
const If = ({children, show}) => show ? children : null
"show" является логическим, и вы используете этот класс по
<If show={true}> Will show </If>
<If show={false}> WON'T show </div> </If>
Я не думаю, что это было упомянуто. Это похоже на ваш собственный ответ, но я думаю, что это еще проще. Вы всегда можете возвращать строки из выражений, и вы можете вложить 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>
мне нравится эксплицитность немедленно вызываемых выражений функций (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() {
}()
что нужно обернуть внутри parens
(function() {
}())
существует также метод, с помощью отображения реквизит для условного отображения компонента. Это преимущество заключается в том, что рендер не будет оценивать, пока условие не будет выполнено, в результате чего не беспокойтесь за null и неопределено значения.
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>
)}
/>
)
}
}
при необходимости отображать что-то, только если переданное условие заполнено, вы можете использовать синтаксис:
{ 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 in в этой статье если вам интересно!
просто добавить еще один вариант-если вам нравится / терпеть кофе-скрипт, вы можете использовать кофе-реагировать, чтобы написать свой JSX, и в этом случае, если / else операторы могут использоваться как выражения в кофе-скрипте, а не операторы:
render: ->
<div className="container">
{
if something
<h2>Coffeescript is magic!</h2>
else
<h2>Coffeescript sucks!</h2>
}
</div>
просто расширить @Jack Allan ответ со ссылками на документы.
React basic (быстрый запуск) документация предлагает null
в таком случае.
Однако,логические значения, Null и Undefined игнорируются а также, упомянутый в расширенном руководстве.