Что эквивалентно ng-if в react.js?


81

Я прихожу, чтобы отреагировать на использование angular, и я пытаюсь найти хорошую альтернативу реакции на директиву angular ng-if, в которой я визуализирую или не визуализирую элемент на основе условия. Возьмем, к примеру, этот код. Я использую машинописный текст (tsx), кстати, но это не имеет большого значения.

"use strict";

import * as React from 'react';

interface MyProps {showMe: Boolean}
interface MyState {}

class Button extends React.Component <MyProps, MyState>{
  constructor(props){
    super(props);
    this.state = {};
  }

  render(){
    let button;
    if (this.props.showMe === true){
       button = (
        <button type="submit" className="btn nav-btn-red">SIGN UP</button>
      )
    } else {
      button = null;
    }
    return button;

}
}
export default Button;

Это решение работает, но есть ли другой способ, который обычно используется для достижения этого эффекта? Я просто догадываюсь



1
Вы использовали правильный метод в react. Использование тернарного оператора сократит ваш код до одной строки, но логика останется прежней. Вы можете использовать пустую или пустую строку (только кавычки), ''если не хотите, чтобы элементы отображались.
Кишор Барик

В последнем официальном документе опубликовано несколько изящных способов сделать это. facebook.github.io/react/docs/…
Даунхиллски

Ответы:


88

Как насчет тернарного оператора ?

render() {
  return (
    this.props.showMe ? <button type="submit" className="btn nav-btn-red">SIGN UP</button> : null
  );
}

Вы также можете использовать &&:

render() {
  return (
    this.props.showMe && <button type="submit" className="btn nav-btn-red">SIGN UP</button>
  );
}

Большой блок, как в комментарии, можно легко обработать, заключив JSX в ()s:

render() {
  return this.props.showMe && (
    <div className="container">
      <button type="submit" className="btn nav-btn-red">
        SIGN UP
      </button>
    </div>
  );
}

Также в строке:

render() {
  return (
    <div className="container">
      {this.props.showMe && <button type="submit" className="btn nav-btn-red">SIGN UP</button>}
    </div>
  );
}

6
а как использовать для более крупных блоков кода? просто встроенный?
Asqan

18
Я тоже думаю, что это нормально, но все же напоминает мне об уродливой смеси PHP и HTML
unlimited101

88
Я скучаю по Angular :(
Удай Хиварале

2
Для меня это намного чище, чем бесконечные хаки и когда лучше всего их использовать. И мне нравится иметь возможность лично оставаться в пространстве javascript-ish.
Саманта Аткинс

1
@PatrickCyiza Не могли бы вы рассказать о своей проблеме? Похоже на проблему поверхностного сравнения.
Yuya

25

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

Код:

import React, {Component} from "react";

class NgIf extends Component {
  render() {
    if (this.props.show) {
      return (
        this.props.children
      );
    } else {
      return null
    }
  }
}

export default NgIf;

Применение:

...
import NgIf from "./path/to/component"
...

class MyClass {
   render(){
      <NgIf show={this.props.show}><Text>This Gets Displayed</Text></NgIf>
   }
}

Я новичок в этом, поэтому, вероятно, можно улучшить, но помогает мне при переходе с Angular

РЕДАКТИРОВАТЬ

См. Правки ниже для лучшего объяснения, когда у меня будет больше опыта

Благодаря комментарию Джея ниже отличная идея также:

render() {
   <View>{this.props.value ? <Text>Yes</Text> : <Text>No</Text>}</View>
}

ИЛИ ЖЕ

render() {
   <View>{this.props.value && <Text>Yes</Text>}</View>
}

Подобно некоторым другим ответам, но работает встроенно, вместо использования всего блока / функции рендеринга не требует специального компонента, и вы можете использовать оператор else с тернарным оператором. Элементы Plus, содержащиеся в операторе if, не вызывают ошибки, если их родительский объект не существует. Т.е. если if props.valueне существует, то props.value.value2не выдаст ошибку.

См. Этот ответ https://stackoverflow.com/a/26152067

РЕДАКТИРОВАТЬ 2:

Согласно приведенной выше ссылке ( https://stackoverflow.com/a/26152067 ) и после гораздо большего опыта разработки приложений для реагирования, описанный выше способ не лучший способ делать что-то.

Условные операторы в react на самом деле очень легко понять. Есть два способа сделать что-то:

//Show if someItem
{someItem && displayThis}

//Show if else
{someItem ? displayThisIfTrue : displayThisIfFalse}

Вы можете сделать одно предостережение, если someItem не является логическим выражением. Если указано, что 0, response будет печатать 0, или response native выдаст вам ошибку о необходимости обернуть «0» в текстовый элемент. Обычно это не проблема для тестов на ложность, но представляет проблему для достоверных тестов. Например:

{!someItem && displayThis} //Will work just fine if item is 0 or null or "" etc
{someItem && displayThis} //Will print the value of someItem if its not falsy

Моя часто используемая уловка? двойные негативы.

{!!someItem && displayThis}

Обратите внимание, что это не относится к тернарным операторам (myVar? True: false), поскольку он неявно преобразует результат в логическое выражение.


1
Мне это нравится больше всего. Использование компонентов и атрибутов для описания логики представления.
Джей Уик

Обновление: посмотрев эти ответы , кажется, что это неидеально.
Джей Уик,

1
Поскольку я новичок в этом, я согласен, это похоже на хороший путь. Один из недостатков моего метода, который я обнаружил, заключается в том, что он по-прежнему будет выдавать ошибку, если элемент, содержащийся в объекте NgIf, ссылается на то, чего не существует. Спасибо, что указали на это
Райан Нелл

1
Я очень ценю, что вы обновили его со временем. Это дает контекст, спасибо!
asiegf

Спасибо за РЕДАКТИРОВАНИЕ 2. Мое предпочтительное решение
TrueKojo

21

Если у вас есть и другие элементы, вы можете обернуть только условное выражение следующим образом:

render() {
  return (
    <div>Stuff</div>
    {this.props.showMe && (
      <button type="submit" className="btn nav-btn-red">SIGN UP</button>
    )}
    <div>More stuff</div>
  );
}

1
Не такой чистый, как некоторые другие предложения, но отлично подходит для одного лайнера!
Joel Davey

11

Немного лучше:

render() {
  return (
    this.props.showMe && <button type="submit" className="btn nav-btn-red">SIGN UP</button>
  );
}

привет, я пытаюсь сделать это, но у меня есть несколько элементов в одном компоненте, и он не работает
user3653796

10

Я просто хотел добавить, что *ngIfв angular не создается экземпляр компонента, к которому он прикреплен. В React, если вы используете оператор if внутри returnоператора, он все равно будет создавать экземпляр компонента, даже если он не отображается. Чтобы добиться истинного *ngIfповедения типа в React, вам нужно создать переменную, которая содержит условный компонент вне returnоператора:

render() {

  const show = false

  return show
     ? <AwesomeComponent />   //still instantiated
     : null
}

render() {

  let c = null
  const show = false

  if (show) {
    c = <AwesomeComponent />   //not instantiated
  }
  return c
}

4

Я могу придумать как минимум три разных способа имитации функциональности ng-if в React.

  • если
  • переключатель
  • IIFE (выражение функции, вызываемой немедленно)

Вы можете прочитать сообщение здесь: Angular, эквивалент ng-if в компоненте React

По сути, вы хотите сделать что-то вроде этого:

var IfDemoComponent = React.createClass({
  render: function() {
    var el = null;
    if (this.props.showMe) {
      el = (
        <div>
          I am only included in the DOM if this.props.showMe evaluates to true.
        </div>
      );
    }
   return el;
  }
});

Спасибо, это меня полностью разблокировало, спасло положение! Спасибо огромное!
Стивен

4

false, null, undefined, И trueявляются действительными детьми. Они просто не отображаются. Все эти JSX-выражения будут отображать одно и то же:

Так что вы можете попробовать это

const conditional=({condition,someArray})=>{
     return(
        <div>
          {condition && <Header /> // condition being boolean} 
          {someArray.length>0 && <Content />}
        </div>
      )
}

это может быть полезно для условного рендеринга элементов React. Этот JSX отображает только условие if и будет отображаться только в том случае, если someArray.length> 0


4

Мне не нравится, когда в коде много тернарных операторов. Вот почему я сделал библиотеку с парочкой полезных компонентов. "RcIf"

  <RcIf if={condition} >
    <h1>I no longer miss ngif</h1>
  </RcIf>
  <RcIf if={othercondition} >
    <h1>I no longer miss v-if</h1>
    <RcElse>
      <h1>I love react</h1>
    </RcElse>
  </RcIf>

Вы можете установить его из npm

https://www.npmjs.com/package/rc-if


3

Я создатель Tersus-jsx.macro и думаю, что этот модуль предоставляет именно то, что необходимо для ответа на этот вопрос.

Вместо того, чтобы смешивать выражения JSX и ES6 для достижения ng-if или ng-repeat, этот макрос позволяет делать то же самое, что и в AngularJS для React JSX, например, для ng-if:

<div>
  <button
    tj-if={a === 0}
    id="gotoA"
    className="link"
    onClick={clicking}
  />
</div>

что эквивалентно

<div>
  {(a === 0) && (
    <button
      id="gotoA"
      className="link"
      onClick={clicking}
    />
  )}
</div>

Учитывая, что последняя версия create-response-app из коробки поддерживает Babel-Macro, все, что вам нужно сделать, это установить этот модуль с помощью npm, обернуть возвращаемый результат рендеринга с помощью «tersus» и начать назначать эти реквизиты.

Вы можете установить это с: https://www.npmjs.com/package/tersus-jsx.macro


Отличный пакет!
secavfr 06

2

Я тоже исхожу из углового фона и искал простой лайнер, чтобы показать тег, если у переменной есть какие-либо элементы. Это сработало для меня:

<div className="comic_creators">
    {c.creators.available > 0 ? <h4>Creators</h4> : null }
    {c.creators.items.map((creator,key) =>
        <Creator creator={creator} key={key}></Creator>
    )}
</div>

0

Я просто создаю метод для использования выражения и двух других аргументов в качестве шаблона на случай, если выражение истина, а другой - вариант шаблона else

export function rif(exp, template, elseTemplate = null) {
    if (exp) {
        return template;
    } else {
        return elseTemplate;
    }
}

и я использую это так

import { rif } from '../utilities';

...
render() {
        return (
            <main role="main" className="container">

                {rif(
                    this.movies.length > 0,
                    <p>Showing {this.movies.length} movies. </p>,
                    <p>There are no movies..</p>
                )}
            </main>
        );
    }

0

Лично мне нравится использовать геттеры, они чистые и гарантируют реактивность:

get toBeDisplayed(){
  const { someLogicState } = this.state;
  if(someLogicState)
    return (
      <div>
        Hi, world !
      </div>
    );
  else
    return null;
}

render(){
  return (<div>{this.toBeDisplayed}</div>);
}

0

Я работаю как угловой, так и реагирую. Я думаю, что angularнеплохо управлять логическим условием с помощью различных директив.

В reactjsэтом подходе работают иначе.

Вы можете использовать if elseусловие , как returnв render functionили ternary operator.

Если еще

  render(){
    
    const auth = true;
    
    if(!auth)
      return(
      <div className="ps-checkout__login">
        <div className="d-flex flex-row">
            <div className="p-2"><img src="../../../static/img/return-customer.png"></img> 
             Returning Customer?</div>
            <div className="p-2"> 
                <Link href="/account/login">
                    <a>                            
                        Click here to login
                    </a>
                </Link>
            </div>
        </div>
    </div>
    )
  else return null;
    }

С тернарным оператором

{ auth?
    (<div className="ps-checkout__login">
        <div className="d-flex flex-row">
            <div className="p-2"><img src="../../../static/img/return-customer.png"></img> 
            Returning Customer?</div>
            <div className="p-2"> 
                <Link href="/account/login">
                    <a>                            
                        Click here to login
                    </a>
                </Link>
            </div>
        </div>
    </div>):null } 
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.