Как мне добавить элемент в 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>
);
}
Просто оставьте баннер undefined и он не включится.
null
работает так же хорошо, как и undefined
? Также это та часть спецификации, что она работает таким образом и, следовательно, вряд ли сломается в будущем?
Как насчет этого. Определите простой компонент 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>
ReactElement
Лично я действительно думаю, что тройные выражения, показанные в 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>
Компонент стиля 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>
);
}
Еще один вариант из реакции issues:
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>
);
}
Вы также можете записать его как
{ this.state.banner && <div>{...}</div> }
Если ваш state.banner
равен null
или undefined
, правая часть условия пропускается.
Этот простой тестовый синтаксис + соглашение о стиле кода + небольшие сфокусированные компоненты для меня - самый читаемый вариант. Вам просто нужно особо соблюдать значения фальши, такие как 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}/>
}
Подробнее здесь: ReactJs - Создание "If" компонент... хорошая идея?
short-circuit syntax
Простой, создайте функцию.
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.
typeof(this.state.price) === "number"
в качестве условия (в любом варианте).
Этот компонент работает, если в ветке "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>
);
}
Я использую более явный ярлык: A Выражение с мгновенной вызывной функцией (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})}/>
}
})()}
Есть другое решение, если компонент для 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>
);
}
Может быть, это помогает кому-то, кто сталкивается с вопросом: Все условные рендеринги в действии Это статья обо всех различных вариантах условного рендеринга в реактиве.
Ключевые выводы о том, когда использовать условный рендеринг:
** if-else
** тернарный оператор
** logical && & Оператор
** корпус переключателя
** перечисления
** многоуровневые/вложенные условные визуализации
** HOCs
** внешние компоненты шаблонов
Вы можете использовать функцию и вернуть компонент и убрать тонкую функцию рендеринга
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 />
}
}
}
Вы можете условно включать элементы, используя тернарный оператор следующим образом:
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>
}
Недавно я сделал https://github.com/ajwhite/render-if, чтобы безопасно отображать элементы только в том случае, если предикат проходит.
{renderIf(1 + 1 === 2)(
<span>Hello!</span>
)}
или
const ifUniverseIsWorking = renderIf(1 + 1 === 2);
//...
{ifUniverseIsWorking(
<span>Hello!</span>
)}
Я сделал https://www.npmjs.com/package/jsx-control-statements, чтобы сделать его немного легче, в основном это позволяет вам определять условные выражения <If>
как теги, а затем компилировать их в trernary ifs, чтобы код внутри <If>
выполнялся только в том случае, если условие истинно.
Существует также метод, использующий рендеринг реквизита для условного рендеринга компонента. Преимущество заключается в том, что рендер не будет оценивать до тех пор, пока условие не будет выполнено, в результате чего не возникнет никаких забот о значениях null и undefined.
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>
)}
}
}
Вот мой подход с использованием 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
- true. Он работает из-за того, как 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
, я считаю это очень хорошим способом условно отобразить некоторые элементы.
Мне нравится объяснение выражений с мгновенной выдержкой (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() {
}())
Я не думаю, что это было упомянуто. Это похоже на ваш собственный ответ, но я думаю, что это еще проще. Вы всегда можете возвращать строки из выражений, и вы можете вставлять 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>
Существует также действительно чистая версия одной строки... {this.props.product.title || "Без названия" }
Т.е:
render: function() {
return (
<div className="title">
{ this.props.product.title || "No Title" }
</div>
);
}
Просто чтобы увеличить @Jack Allan ответ со ссылками на документы.
В этом случае рекомендуется базовая документация (Quick Start) null
.
Однако Booleans, Null и Undefined Игнорируются, упомянутые в Расширенном руководстве.
Просто добавьте еще один вариант - если вы любите/терпите кофе script, вы можете использовать кофе-реактив, чтобы написать свой JSX, в этом случае, если/else-заявления можно использовать, поскольку они являются выражениями в кофе- script, а не заявления:
render: ->
<div className="container">
{
if something
<h2>Coffeescript is magic!</h2>
else
<h2>Coffeescript sucks!</h2>
}
</div>
else
ветки, это работает? Я не знаком с JSX ...