Когда вы объявляете ссылочную переменную (т. е. объект), вы действительно создаете указатель на объект. Рассмотрим следующий код, в котором вы объявляете переменную примитивного типа int
:
int x;
x = 10;
В этом примере переменная x является int
, и Java инициализирует ее для 0. Когда вы назначаете его 10 во второй строке, ваше значение 10 записывается в ячейку памяти, на которую указывает x.
Но когда вы пытаетесь объявить ссылочный тип, произойдет что-то другое. Возьмите следующий код:
Integer num;
num = new Integer(10);
Первая строка объявляет переменную с именем num
, но она не содержит примитивного значения. Вместо этого он содержит указатель (потому что тип Integer
является ссылочным типом). Поскольку вы еще не указали, что указать на Java, он устанавливает значение null, что означает «Я ничего не указываю».
Во второй строке ключевое слово new
используется для создания экземпляра (или создания ) объекту типа Integer и переменной указателя num
присваивается этот объект. Теперь вы можете ссылаться на объект, используя оператор разыменования .
(точка).
Exception
, о котором вы просили, возникает, когда вы объявляете переменную, но не создавали объект. Если вы попытаетесь разыменовать num
. Перед созданием объекта вы получите NullPointerException
. В самых тривиальных случаях компилятор поймает проблему и сообщит вам, что «num не может быть инициализирован», но иногда вы пишете код, который непосредственно не создает объект.
Например, вы можете имеют следующий метод:
public void doSomething(SomeObject obj) {
//do something to obj
}
В этом случае вы не создаете объект obj
, скорее предполагая, что он был создан до вызова метода doSomething
. К сожалению, этот метод можно вызвать следующим образом:
doSomething(null);
В этом случае obj
имеет значение null. Если метод предназначен для того, чтобы что-то сделать для переданного объекта, целесообразно бросить NullPointerException
, потому что это ошибка программиста, и программисту понадобится эта информация для целей отладки.
Альтернативно, там могут быть случаи, когда цель метода заключается не только в том, чтобы работать с переданным в объекте, и поэтому нулевой параметр может быть приемлемым. В этом случае вам нужно будет проверить нулевой параметр и вести себя по-другому. Вы также должны объяснить это в документации. Например, doSomething
может быть записано как:
/**
* @param obj An optional foo for ____. May be null, in which case
* the result will be ____.
*/
public void doSomething(SomeObject obj) {
if(obj != null) {
//do something
} else {
//do something else
}
}
Наконец, Как определить исключение & amp; причина использования Трассировки стека
Просто оставляйте баннер неопределенным и не включается.
Я сделал https://www.npmjs.com/package/jsx-control-statements , чтобы сделать его немного легче, в основном это позволяет вам определить условные обозначения <If>
как теги, а затем компилирует их в trernary ifs, чтобы код внутри <If>
выполнялся только в том случае, если условие истинно.
Недавно я сделал https://github.com/ajwhite/render-if , чтобы безопасно отображать элементы только в том случае, если предикат проходит.
{renderIf(1 + 1 === 2)(
<span>Hello!</span>
)}
или
const ifUniverseIsWorking = renderIf(1 + 1 === 2);
//...
{ifUniverseIsWorking(
<span>Hello!</span>
)}
Экспериментальный синтаксис 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
Компонент стиля 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>
);
}
Этот простой тестовый синтаксис + соглашение о стиле кода + небольшие сфокусированные компоненты для меня - самый читаемый вариант. Вам просто нужно особо соблюдать значения фальши, такие как 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 - Создание & quot; If & quot; компонент ... хорошая идея?
short-circuit syntax
– sospedra
29 March 2017 в 09:28
Мне нравится объяснение выражений с мгновенной вызывной функцией (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() {
}())
Существует другое решение, , если компонент для 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>
);
}
Просто добавьте еще один вариант - если вы любите / терпите кофе-скрипт, вы можете использовать кофе-ответ, чтобы написать свой JSX, в этом случае, если / else-заявления можно использовать, поскольку они являются выражениями в сценарии кофе, а не в операторах:
render: ->
<div className="container">
{
if something
<h2>Coffeescript is magic!</h2>
else
<h2>Coffeescript sucks!</h2>
}
</div>
Большинство примеров относятся к одной строке «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>
);
}
Лично я действительно думаю, что тройные выражения, показанные в , 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>
Я использую более явный ярлык: 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})}/>
}
})()}
Я не думаю, что это было упомянуто. Это похоже на ваш собственный ответ, но я думаю, что это еще проще. Вы всегда можете возвращать строки из выражений, и вы можете вставлять внутренние выражения 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>
Этот компонент работает, когда у вас есть более одного элемента внутри ветки «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 хуже
С ES6 вы можете сделать это с помощью простого однострочного
const If = ({children, show}) => show ? children : null
«show» является логическим, и вы используете этот класс с помощью
<If show={true}> Will show </If>
<If show={false}> WON'T show </div> </If>
Как уже упоминалось в ответах, 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"
в качестве условия (в любом варианте).
– Kroltan
4 October 2016 в 19:58
Вы можете условно включать элементы, используя тернарный оператор следующим образом:
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>
}
Существует также действительно чистая версия одной строки ... {this.props.product.title || «Нет названия»}
То есть:
render: function() {
return (
<div className="title">
{ this.props.product.title || "No Title" }
</div>
);
}
Вы также можете записать его как
{ this.state.banner && <div>{...}</div> }
Если ваш state.banner
равен null
или undefined
, правая часть условия пропущена.
Когда нужно только выполнить что-либо, если пройденное условие заполнено, вы можете использовать синтаксис:
{ 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 в этой статье , если вам интересно!
Просто для того, чтобы увеличить @Jack Allan ответ со ссылками на документы.
Документация React basic (Quick Start) предлагает в этом случае null
. Однако Booleans, Null и Undefined также игнорируются , упомянутые в Расширенном руководстве.
Вы можете использовать функцию и вернуть компонент и удержать тонкую функцию рендеринга
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 />
}
}
}
Существует также метод, использующий рендеринг рендеринга для условного рендеринга компонента. Выгода заключается в том, что рендер не будет оценивать до тех пор, пока условие не будет удовлетворено, в результате чего не возникнет никаких опасений по поводу значений 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
истинно. Он работает из-за того, как 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
, я нахожу его очень хорошим способом условно отображать некоторые элементы.
Возможно, это помогает кому-то, кто сталкивается с вопросом: Все условные рендеринги в действии Это статья обо всех различных вариантах условного рендеринга в React.
Выводы о том, когда использовать, какой условный рендеринг:
** if-else
** тернарный оператор
** logical & amp; & amp; & amp; оператор
** случай переключения
** перечисления
** многоуровневых / вложенных условных визуализаций
** HOC
** внешних шаблонных компонентах
Как насчет этого. Давайте определим простой компонент 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
– srph
9 January 2015 в 18:26
Простой, создайте функцию.
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
в свой собственный компонент, если он становится слишком большим (или повторно используется в других местах).
null
так же, какundefined
? Также является ли это частью спецификации, что она работает таким образом и, следовательно, вряд ли будет разорваться в будущем? – hippietrail 8 September 2017 в 04:07