React показывает 0 вместо ничего с условным компонентом короткого замыкания (&&)

У меня есть следующий простой оператор короткого замыкания, который должен показывать либо компонент, либо ничего:

{profileTypesLoading && <GeneralLoader />}

Если утверждение ложно, оно отображает 0 вместо ничего.

Я сделал console.log(profileTypesLoading) только для того, чтобы быстро посмотреть, каково состояние свойства profileTypesLoading, и оно либо 1, либо 0, как и ожидалось. 0 должно быть ложным... ничего не рендерится. Верно?

Любая идея, почему это произойдет?


person Gurnzbot    schedule 29.10.2018    source источник


Ответы (4)


Поскольку ваше условие ложно и поэтому не возвращает второй аргумент (<GeneralLoader />), оно вернет profileTypesLoading, то есть число, поэтому реакция отобразит его, потому что React пропускает рендеринг для всего, что typeof boolean или undefined и отобразит все, что typeof string или number:

Чтобы сделать это безопасным, вы можете использовать троичное выражение {condition ? <Component /> : null} или логическое выражение, например {!!condition && <Component />}

person enapupe    schedule 29.10.2018
comment
Я приму это, как только мне разрешат через 3 минуты... но спасибо, это имеет смысл. Я удивлен, что этого нет ни в одном из объяснений, которые я читал по этому методу. Это всегда было просто написано, как я написал. Без кастинга. Урок выучен! - person Gurnzbot; 29.10.2018
comment
Вы также можете использовать оператор Boolean, если !!condition вас смущает. Что-то вроде { Boolean(condition) && <Component /> } - person vijayscode; 10.05.2019
comment
таблица истинности реакции: jsfiddle.net/milahu/k2z3wocm/5 - person Mila Nautikus; 18.08.2020

0 является ложным значением, поэтому, когда оно оценивается с помощью &&, оно возвращает 0. Однако 0 может отображаться React, поскольку это количество:

// Renderable values
1 && <GeneralLoader /> // => Renders <GeneralLoader />
"a string" && <GeneralLoader /> // => Renders <GeneralLoader />
0 && <GeneralLoader /> // => Renders '0'

// Non-renderable values
false && <GeneralLoader /> // => Renders nothing
null && <GeneralLoader /> // => Renders nothing
undefined && <GeneralLoader /> // => Renders nothing

TLDR

Это связано с тем, как сам javascript обрабатывает [истинные и ложные значения][1]:

В JavaScript истинное значение — это значение, которое считается истинным при встрече в логическом контексте. Все значения являются истинными, если только они не определены как ложные (т. е. за исключением ложных, 0, "", null, undefined и NaN).

При использовании с оператором && возвращаемое значение зависит от левого значения:

  • Если левое значение истинно, возвращается правое значение.
  • Если левое значение ложно, возвращается его значение.

Примеры:

// Truthy values
1 && "hello" // => "hello"
"a string" && "hello" // => "hello"

// Falsy values
0 && "hello" // => 0
false && "hello" // => false
null && "hello" // => null
undefined && "hello" // => undefined

Те же правила применяются к JSX, потому что это [расширение синтаксиса JavaScript][2]. Однако проблема в том, что **

Проблема в том, что 0 является ложным значением, поэтому, когда оно оценивается с помощью &&, оно возвращает 0. Однако 0 визуализируется React, потому что это число

// Renderable values
1 && <GeneralLoader /> // => Renders <GeneralLoader />
"a string" && <GeneralLoader /> // => Renders <GeneralLoader />
0 && <GeneralLoader /> // => Renders 0

// Non-renderable values
false && <GeneralLoader /> // => Renders nothing
null && <GeneralLoader /> // => Renders nothing
undefined && <GeneralLoader /> // => Renders nothing
person Giovanni Benussi    schedule 15.08.2019

Это решит проблему:

{!!profileTypesLoading && <GeneralLoader />}

Поскольку он преобразует 0 в false. Причина в том, что когда это 0, следующее условие не выполняется, и оно ведет себя как число в JavaScript, поэтому здесь помогает двойное отрицание.

person Sakhi Mansoor    schedule 29.10.2018
comment
Вы также можете сделать {profileTypesLoading > 0 && <GeneralLoader />} как React документы говорят - person Guilherme Samuel; 07.02.2021

Чтобы сначала оценить ложное условие, проще всего использовать константу с тернаром. Пример:

В этом случае отображается простая кнопка, если параметр someCollectionProperty пуст, в противном случае будет показана кнопка с меню некоторых параметров (пример пользовательского интерфейса материала).

export default function MyComponent({ obj }) {

  const jsxResponse = !obj.someCollecctionProperty.length ? <Button>No Action</Button> 
    : 
    <>
      <Button 
        aria-label="more"
        aria-controls="long-menu"
        aria-haspopup="true" 
        variant="contained" 
        onClick={handleClick} 
        color={'primary'}>
          <ThumbUpAltOutlinedIcon/>OK
      </Button>
      <Menu
        id="long-menu"
        anchorEl={anchorEl}
        keepMounted
        open={open}
        onClose={handleClose}
      >
        {obj.someCollecctionProperty.map((option) => (
          <MenuItem key={option.id} onClick={handleClose}>
            <Avatar variant="square" alt={option.name} src={option.url}/>{option.configName}
          </MenuItem>
        ))}
      </Menu>
    </>;

  return (<div>{jsxResponse}</div>);
}

jsxResponse - это визуализируемый компонент, с этим можно избежать 0 при просмотре

person nilsoviani    schedule 03.08.2021