Pokaż lub ukryj element w React

532

Po raz pierwszy bawię się React.js i nie mogę znaleźć sposobu, aby pokazać lub ukryć coś na stronie poprzez zdarzenie click. Nie ładuję żadnej innej biblioteki na stronę, więc szukam natywnego sposobu korzystania z biblioteki React. To właśnie mam. Chciałbym wyświetlić div wyników, gdy zadziała zdarzenie kliknięcia.

var Search= React.createClass({
    handleClick: function (event) {
        console.log(this.prop);
    },
    render: function () {
        return (
            <div className="date-range">
                <input type="submit" value="Search" onClick={this.handleClick} />
            </div>
        );
    }
});

var Results = React.createClass({
    render: function () {
        return (
            <div id="results" className="search-results">
                Some Results
            </div>
        );
    }
});

React.renderComponent(<Search /> , document.body);
użytkownik1725382
źródło
11
Zaakceptowany komentarz wykorzystuje nowatorską technologię do robienia tego, co istniejące technologie na poziomie natywnym mogą zrobić łatwiej, szybciej i współdzieląc z innymi językami i bibliotekami. Obsługa tego przy użyciu standardowego CSS jest prawie na pewno lepszą odpowiedzią.
John Haugeland,
13
@JohnHaugeland, najlepszą odpowiedzią podczas korzystania z frameworka React jest zaakceptowana odpowiedź, w stylu React, który ma funkcje czyszczenia, które w niektórych przypadkach należy wykonać. Nie jest dobrą praktyką, aby komponenty ukrywały się w ciemności. Jeśli miksujesz różne rzeczy, lepiej zacząć wszystko natywnie, co zawsze jest szybsze niż cokolwiek innego.
Claudiu Hojda
4
Nie, tak naprawdę nie jest. Korzystanie z reagowania w celu ponownego opracowania CSS jest złym pomysłem.
John Haugeland,
8
Poza tym wydaje się, że zupełnie nie rozumiesz tego, co powiedziałem, a mianowicie użycia CSS do ukrywania i pokazywania elementu, zamiast używania React do jego fizycznego usunięcia. Państwo może używać React użyć CSS, aby ukryć i pokazać element równie dobrze: <div style = {{display: this.props.example}} />.
John Haugeland,
5
@ClaudiuHojda ukrywanie komponentów w ciemności jest w rzeczywistości bardzo dobrą praktyką, w niektórych przypadkach myślę o responsywnej nawigacji, w której potrzebujesz linków, aby pozostać w HTML, nawet jeśli są ukryte za pomocą css
Toni Leigh

Odpowiedzi:

544

Reaguj około 2020 roku

W onClickwywołaniu zwrotnym wywołaj funkcję ustawiania haka stanu, aby zaktualizować stan i ponownie renderować:

const Search = () => {
  const [showResults, setShowResults] = React.useState(false)
  const onClick = () => setShowResults(true)
  return (
    <div>
      <input type="submit" value="Search" onClick={onClick} />
      { showResults ? <Results /> : null }
    </div>
  )
}

const Results = () => (
  <div id="results" className="search-results">
    Some Results
  </div>
)

ReactDOM.render(<Search />, document.querySelector("#container"))
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.13.1/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.13.1/umd/react-dom.production.min.js"></script>

<div id="container">
  <!-- This element's contents will be replaced with your component. -->
</div>

JSFiddle

Reaguj około 2014 roku

Kluczem jest aktualizacja stanu komponentu w module obsługi kliknięć za pomocą setState. Kiedy zmiany stanu zostaną zastosowane, rendermetoda zostanie ponownie wywołana z nowym stanem:

var Search = React.createClass({
    getInitialState: function() {
        return { showResults: false };
    },
    onClick: function() {
        this.setState({ showResults: true });
    },
    render: function() {
        return (
            <div>
                <input type="submit" value="Search" onClick={this.onClick} />
                { this.state.showResults ? <Results /> : null }
            </div>
        );
    }
});

var Results = React.createClass({
    render: function() {
        return (
            <div id="results" className="search-results">
                Some Results
            </div>
        );
    }
});

ReactDOM.render( <Search /> , document.getElementById('container'));
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.6.2/react.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/15.6.2/react-dom.min.js"></script>

<div id="container">
  <!-- This element's contents will be replaced with your component. -->
</div>

JSFiddle

Douglas
źródło
3
Tak, dobra uwaga na temat stanu vs. rekwizyty. Lepszym sposobem na zrobienie tego może być ten samouczek, w którym pasek wyszukiwania i tabela wyników są rodzeństwem, zamiast umieszczania wyników w Wyszukiwarce: facebook.github.io/react/docs/thinking-in-react.html
Douglas
53
Jak zauważono w drugiej odpowiedzi, wstawianie / usuwanie jest znacznie wolniejsze niż zwykłe maskowanie klas.
John Haugeland,
4
Myślę, że komentarze Johnsa wymagają przeglądu. Poszedłem z zamierzoną odpowiedzią, która była fajna i „czułem” się bardziej reagować. Nie byłem jednak w stanie ustawić stanów początkowych ani niczego przydatnego w niezamontowanym komponencie. Zamiast tego szukam css do ukrywania rzeczy. Słuchacze niezamontowanych komponentów po cichu zawiodą, co spowodowało dziś dużą stratę czasu.
wylądował
Czy to oznacza, że ​​reakcja spowoduje ponowne przesłanie komponentu, gdy styl się zmieni (ustawiony na pokazywanie / ukrywanie)!?
Alex
@Douglas, chyba że mi go brakowało, ten sposób nie pozwala na powrót do oryginału. Myślę, że OP mógł tego nie chcieć, ale jak mogę to włączyć?
Robak
221
<style type="text/css">
    .hidden { display:none; }
</style>
render: function() {
    return (
      <div className={this.props.shouldHide ? 'hidden' : ''}>
        This will be hidden if you set <tt>props.shouldHide</tt> 
        to something truthy.
      </div>
    );
}

// or in more modern JS and stateless react
const Example = props => <div className={props.shouldHide}/>Hello</div>
John Haugeland
źródło
12
Lepiej warunkowo zwrócić wartość null, jak w odpowiedzi Douglasa. To pozwala React całkowicie usunąć go z DOM. W twoim przypadku div i jego zawartość nadal są w DOM po prostu się nie wyświetlają. Może to mieć wpływ na wydajność.
pmont
125
Wpływ na wydajność jest znacznie gorszy przy dodawaniu i usuwaniu elementu dom niż na ukrywanie i pokazywanie go. Zdaję sobie sprawę z różnicy między jego podejściem a moim, i wierzę, że źle to rozumiesz. Proszę rozważyć poświęcenie czasu na zdefiniowanie „wpływu na wydajność”, a następnie zmierzenie go.
John Haugeland,
6
„Przepływy są gwarantowane przy dodawaniu / usuwaniu” - Nie przy elementach absolutnie pozycjonowanych, dzięki czemu Famous uzyskuje niesamowitą wydajność. Ale robisz ważny punkt na temat wskaźników.
pont
9
za to, co jest warte, jest to wspomniane w dokumentach reagujących tutaj: facebook.github.io/react/docs/…
Brad Parks
85
Właśnie przetestowałem zwracanie wartości null vs. ustawienie ukrytej klasy z 161 dość dużymi węzłami domowymi. Korzystanie z klasy jest znacznie szybsze niż usuwanie węzła.
Jonathan Rowny
120

Oto alternatywna składnia dla operatora trójskładnikowego:

{ this.state.showMyComponent ? <MyComponent /> : null }

jest równa:

{ this.state.showMyComponent && <MyComponent /> }

Oprzyj się dlaczego


Również alternatywna składnia z display: 'none';

<MyComponent style={this.state.showMyComponent ? {} : { display: 'none' }} />

Jeśli jednak nadużyjesz display: 'none', prowadzi to do zanieczyszczenia DOM i ostatecznie spowalnia aplikację.

Lyubomir
źródło
Ostrzeżenie! Stosuj podejście „podwójny znak ampersand (&&)” tylko dla wartości bool. {this.state.myComponents.length && <MyComponent />} wyrenderuje 0, jeśli myComponents pusta tablica (na przykład)
Mega Proger
57

Oto moje podejście.

import React, { useState } from 'react';

function ToggleBox({ title, children }) {
  const [isOpened, setIsOpened] = useState(false);

  function toggle() {
    setIsOpened(wasOpened => !wasOpened);
  }

  return (
    <div className="box">
      <div className="boxTitle" onClick={toggle}>
        {title}
      </div>
      {isOpened && (
        <div className="boxContent">
          {children}
        </div>
      )}
    </div>
  );
}

W powyższym kodzie, aby to osiągnąć, używam kodu takiego jak:

{opened && <SomeElement />}

Uczyni to SomeElementtylko wtedy, gdy openedbędzie to prawdą. Działa ze względu na sposób, w jaki JavaScript rozwiązuje warunki logiczne:

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 (and false will be ignored by react during rendering)
// be careful with 'falsy' values eg
const someValue = 0;
someValue && <SomeElement /> // will output 0, which will be rednered by react
// it'll be better to:
!!someValue && <SomeElement /> // will render nothing as we cast the value to boolean

Powody stosowania tego podejścia zamiast CSS „display: none”;

  • Chociaż ukrywanie elementu za pomocą CSS może być „tańsze” - w takim przypadku element „ukryty” jest nadal „żywy” w świecie reagowania (co może w rzeczywistości uczynić go znacznie droższym)
    • oznacza to, że jeśli rekwizyty elementu nadrzędnego (np. <TabView>) zmienią się - nawet jeśli zobaczysz tylko jedną kartę, wszystkie 5 kart zostanie ponownie renderowanych
    • element ukryty może nadal mieć uruchomione niektóre metody cyklu życia - np. może pobierać niektóre dane z serwera po każdej aktualizacji, nawet jeśli nie jest to widoczne
    • ukryty element może spowodować awarię aplikacji, jeśli otrzyma nieprawidłowe dane. Może się tak zdarzyć, ponieważ można „zapomnieć” o niewidocznych węzłach podczas aktualizacji stanu
    • możesz przez pomyłkę ustawić zły styl „wyświetlania” podczas wyświetlania elementu - np. niektóre div jest domyślnie „display: flex”, ale przez pomyłkę ustawisz „display: block”display: invisible ? 'block' : 'none' co może zepsuć układ
    • używanie someBoolean && <SomeNode />jest bardzo łatwe do zrozumienia i uzasadnienia, szczególnie jeśli twoja logika związana z wyświetlaniem czegoś lub nie jest skomplikowana
    • w wielu przypadkach chcesz zresetować stan elementu, gdy pojawi się ponownie. na przykład. możesz mieć suwak, który chcesz ustawić w pozycji początkowej za każdym razem, gdy jest pokazywany. (jeśli jest to pożądane zachowanie, aby zachować poprzedni stan elementu, nawet jeśli jest ukryty, co IMO jest rzadkie - rzeczywiście rozważę użycie CSS, jeśli zapamiętanie tego stanu w inny sposób byłoby skomplikowane)
pie6k
źródło
2
To świetny przykład! Jedna drobna rzecz, boxContent powinien być className = "boxContent"
Bhetzie
5
Jest to błąd tu: this.setState({isOpened: !isOpened});. Podczas modyfikowania stanu nie należy polegać na samym stanie. Oto przykład dobre: reactjs.org/docs/... Tak powinno być: this.setState( s => ({isOpened: !s.isOpened}) ). Zwróć uwagę na funkcję strzałki wewnątrz setState.
arcol
Czy masz jakieś źródło / test / przykład potwierdzający to: „Jeśli ustawisz display: none - element jest nadal renderowany przez reakcję i dodawany do DOM - co może mieć zły wpływ na wydajność”. ?
neiya
@neiya nie. CSS może być bardziej wydajny z małymi elementami, ale dość często chcesz renderować opcjonalnie duże części treści, np. patka. Ponadto, chociaż jakiś element jest ukryty w CSS - wciąż żyje w świecie reagowania. Oznacza to, że może zaktualizować swój stan, pobrać dane itp., Które mogą być drogie i prowadzić do nieoczekiwanego zachowania. I jest to w rzeczywistości bardzo proste do wdrożenia.
pie6k
17

w najnowszej wersji reagują na 0.11, możesz też po prostu zwrócić null, aby nie renderować treści.

Renderowanie do zera

kałamarnica
źródło
11

Stworzyłem mały komponent, który obsługuje to za Ciebie: reaguj-przełącz-wyświetl

Ustawia atrybut stylu na display: none !importantna podstawie hidelubshow rekwizytów .

Przykładowe użycie:

var ToggleDisplay = require('react-toggle-display');

var Search = React.createClass({
    getInitialState: function() {
        return { showResults: false };
    },
    onClick: function() {
        this.setState({ showResults: true });
    },
    render: function() {
        return (
            <div>
                <input type="submit" value="Search" onClick={this.onClick} />
                <ToggleDisplay show={this.state.showResults}>
                    <Results />
                </ToggleDisplay>
            </div>
        );
    }
});

var Results = React.createClass({
    render: function() {
        return (
            <div id="results" className="search-results">
                Some Results
            </div>
        );
    }
});

React.renderComponent(<Search />, document.body);
ccnokes
źródło
10

Jest już kilka świetnych odpowiedzi, ale nie sądzę, że zostały one wyjaśnione bardzo dobrze, a kilka z podanych metod zawiera pewne gotówki, które mogą wprawić ludzi w osłupienie. Omówię trzy główne sposoby (plus jedna opcja nie na temat), aby to zrobić i wyjaśnić zalety i wady. Piszę to głównie, ponieważ Opcja 1 była bardzo zalecana i istnieje wiele potencjalnych problemów z tą opcją, jeśli nie zostanie użyta poprawnie.

Opcja 1: Renderowanie warunkowe w obiekcie nadrzędnym.

Nie podoba mi się ta metoda, chyba że zamierzasz renderować komponent tylko raz i zostawić go tam. Problem polega na tym, że spowoduje to reakcję na tworzenie komponentu od zera za każdym razem, gdy zmienisz widoczność. Oto przykład. LogoutButton lub LoginButton są warunkowo renderowane w nadrzędnym LoginControl. Jeśli to uruchomisz, zauważysz, że konstruktor jest wywoływany przy każdym kliknięciu przycisku. https://codepen.io/Kelnor/pen/LzPdpN?editors=1111

class LoginControl extends React.Component {
  constructor(props) {
    super(props);
    this.handleLoginClick = this.handleLoginClick.bind(this);
    this.handleLogoutClick = this.handleLogoutClick.bind(this);
    this.state = {isLoggedIn: false};
  }

  handleLoginClick() {
    this.setState({isLoggedIn: true});
  }

  handleLogoutClick() {
    this.setState({isLoggedIn: false});
  }

  render() {
    const isLoggedIn = this.state.isLoggedIn;

    let button = null;
    if (isLoggedIn) {
      button = <LogoutButton onClick={this.handleLogoutClick} />;
    } else {
      button = <LoginButton onClick={this.handleLoginClick} />;
    }

    return (
      <div>
        <Greeting isLoggedIn={isLoggedIn} />
        {button}
      </div>
    );
  }
}

class LogoutButton extends React.Component{
  constructor(props, context){
    super(props, context)
    console.log('created logout button');
  }
  render(){
    return (
      <button onClick={this.props.onClick}>
        Logout
      </button>
    );
  }
}

class LoginButton extends React.Component{
  constructor(props, context){
    super(props, context)
    console.log('created login button');
  }
  render(){
    return (
      <button onClick={this.props.onClick}>
        Login
      </button>
    );
  }
}

function UserGreeting(props) {
  return <h1>Welcome back!</h1>;
}

function GuestGreeting(props) {
  return <h1>Please sign up.</h1>;
}

function Greeting(props) {
  const isLoggedIn = props.isLoggedIn;
  if (isLoggedIn) {
    return <UserGreeting />;
  }
  return <GuestGreeting />;
}

ReactDOM.render(
  <LoginControl />,
  document.getElementById('root')
);

Teraz React bardzo szybko tworzy komponenty od zera. Jednak nadal musi wywoływać kod podczas jego tworzenia. Więc jeśli twój konstruktor, składnik componentDidMount, renderowanie itp. Jest drogi, wówczas znacznie spowolni wyświetlanie komponentu. Oznacza to również, że nie można tego używać z komponentami stanowymi, w których chcesz zachować stan, gdy jest ukryty (i przywracany, gdy jest wyświetlany). Jedną zaletą jest to, że ukryty komponent nie jest tworzony, dopóki nie zostanie wybrany. Ukryte komponenty nie opóźnią początkowego ładowania strony. Mogą również wystąpić sytuacje, w których CHCESZ stanowy komponent zresetować po przełączeniu. W takim przypadku jest to najlepsza opcja.

Opcja 2: Renderowanie warunkowe u dziecka

To tworzy oba komponenty jeden raz. Następnie zewrzyj resztę kodu renderowania, jeśli komponent jest ukryty. Możesz także zwierać inną logikę innymi metodami, używając widocznego rekwizytu. Zwróć uwagę na plik console.log na stronie codepen. https://codepen.io/Kelnor/pen/YrKaWZ?editors=0011

class LoginControl extends React.Component {
  constructor(props) {
    super(props);
    this.handleLoginClick = this.handleLoginClick.bind(this);
    this.handleLogoutClick = this.handleLogoutClick.bind(this);
    this.state = {isLoggedIn: false};
  }

  handleLoginClick() {
    this.setState({isLoggedIn: true});
  }

  handleLogoutClick() {
    this.setState({isLoggedIn: false});
  }

  render() {
    const isLoggedIn = this.state.isLoggedIn;
    return (
      <div>
        <Greeting isLoggedIn={isLoggedIn} />
        <LoginButton isLoggedIn={isLoggedIn} onClick={this.handleLoginClick}/>
        <LogoutButton isLoggedIn={isLoggedIn} onClick={this.handleLogoutClick}/>
      </div>
    );
  }
}

class LogoutButton extends React.Component{
  constructor(props, context){
    super(props, context)
    console.log('created logout button');
  }
  render(){
    if(!this.props.isLoggedIn){
      return null;
    }
    return (
      <button onClick={this.props.onClick}>
        Logout
      </button>
    );
  }
}

class LoginButton extends React.Component{
  constructor(props, context){
    super(props, context)
    console.log('created login button');
  }
  render(){
    if(this.props.isLoggedIn){
      return null;
    }
    return (
      <button onClick={this.props.onClick}>
        Login
      </button>
    );
  }
}

function UserGreeting(props) {
  return <h1>Welcome back!</h1>;
}

function GuestGreeting(props) {
  return <h1>Please sign up.</h1>;
}

function Greeting(props) {
  const isLoggedIn = props.isLoggedIn;
  if (isLoggedIn) {
    return <UserGreeting />;
  }
  return <GuestGreeting />;
}

ReactDOM.render(
  <LoginControl />,
  document.getElementById('root')
);

Teraz, jeśli logika inicjalizacji jest szybka, a dzieci są bezstanowe, nie zobaczysz różnicy w wydajności lub funkcjonalności. Dlaczego jednak React tworzy i tak nowy element przy każdym przełączaniu? Jeśli inicjalizacja jest jednak droga, opcja 1 uruchomi ją za każdym razem, gdy przełączysz komponent, co spowolni stronę podczas przełączania. Opcja 2 uruchomi wszystkie inicjały składnika przy ładowaniu pierwszej strony. Spowolnienie pierwszego obciążenia. Należy zanotować ponownie. Jeśli wyświetlasz komponent tylko raz w oparciu o warunek i nie przełączasz go, lub chcesz, aby zresetował się po przełączeniu, to opcja 1 jest w porządku i prawdopodobnie najlepsza opcja.

Jeśli jednak powolne ładowanie strony stanowi problem, oznacza to, że masz kosztowny kod w metodzie cyklu życia i ogólnie nie jest to dobry pomysł. Możesz i prawdopodobnie powinieneś rozwiązać powolne ładowanie strony, usuwając kosztowny kod z metod cyklu życia. Przenieś go do funkcji asynchronicznej uruchomionej przez ComponentDidMount, a wywołanie zwrotne umieść ją w zmiennej stanu za pomocą setState (). Jeśli zmienna stanu ma wartość NULL, a komponent jest widoczny, funkcja renderowania zwraca symbol zastępczy. W przeciwnym razie wyrenderuj dane. W ten sposób strona ładuje się szybko i zapełnia karty podczas ładowania. Możesz także przenieść logikę do rodzica i przekazać wyniki dzieciom jako rekwizyty. W ten sposób możesz ustalić, które karty będą ładowane jako pierwsze. Lub buforuj wyniki i uruchamiaj logikę tylko przy pierwszym wyświetleniu komponentu.

Opcja 3: Ukrywanie klas

Ukrywanie klas jest prawdopodobnie najłatwiejsze do wdrożenia. Jak wspomniano, po prostu tworzysz klasę CSS z display: none i przypisujesz klasę na podstawie prop. Minusem jest to, że wywoływany jest cały kod każdego ukrytego komponentu, a wszystkie ukryte komponenty są dołączane do DOM. (Opcja 1 w ogóle nie tworzy ukrytych komponentów. Opcja 2 powoduje zwarcie niepotrzebnego kodu, gdy komponent jest ukryty i całkowicie usuwa komponent z DOM). Wygląda na to, że szybsze przełączanie widoczności jest szybsze według niektórych testów przeprowadzonych przez komentujących inne odpowiedzi, ale nie mogę z tym rozmawiać.

Opcja 4: jeden element, ale zmień rekwizyty. A może żaden komponent i buforuj HTML.

Ten nie będzie działał dla każdej aplikacji i jest nie na temat, ponieważ nie dotyczy ukrywania komponentów, ale może być lepszym rozwiązaniem w niektórych przypadkach użycia niż ukrywanie. Powiedzmy, że masz karty. Może być możliwe napisanie jednego React Component i po prostu użycie rekwizytów, aby zmienić to, co wyświetla się na karcie. Możesz także zapisać JSX do zmiennych stanu i użyć rekwizytu, aby zdecydować, który JSX ma zostać zwrócony w funkcji renderowania. Jeśli JSX musi zostać wygenerowany, zrób to i buforuj go w obiekcie nadrzędnym i wyślij poprawny jako rekwizyt. Lub wygeneruj w dziecku i buforuj go w stanie dziecka i użyj rekwizytów, aby wybrać aktywny.

Kelnor
źródło
9

To dobry sposób na wykorzystanie wirtualnego DOM :

class Toggle extends React.Component {
  state = {
    show: true,
  }

  toggle = () => this.setState((currentState) => ({show: !currentState.show}));

  render() {
    return (
      <div>
        <button onClick={this.toggle}>
          toggle: {this.state.show ? 'show' : 'hide'}
        </button>    
        {this.state.show && <div>Hi there</div>}
      </div>
     );
  }
}

Przykład tutaj

Korzystanie z haków React:

const Toggle = () => {
  const [show, toggleShow] = React.useState(true);

  return (
    <div>
      <button
        onClick={() => toggleShow(!show)}
      >
        toggle: {show ? 'show' : 'hide'}
      </button>    
      {show && <div>Hi there</div>}
    </div>
  )
}

Przykład tutaj

daniloprates
źródło
Podoba mi się ta szczupła odpowiedź. Szkoda, że ​​skrzypce nie chce biec.
Juan Lanus
Jak wspomniano we wcześniejszej odpowiedzi, nie powinieneś polegać na stanie wthis.setState() .
Dan Dascalescu
8

Ustawiasz wartość logiczną w stanie (np. „Pokaż)”, a następnie:

var style = {};
if (!this.state.show) {
  style.display = 'none'
}

return <div style={style}>...</div>
Bandyta
źródło
Próbowałem tego, ale zdarzenie click nie przełączyło css do bloku wyświetlania. Jestem zagubiony w tym, jak to osiągnąć. Jakieś dodatkowe wskazówki?
user1725382
1
Obejmuje to dokonywanie aktywnych zmian w tabeli reguł stylów. O wiele lepiej jest mieć jedną istniejącą regułę, którą można włączać i wyłączać, która nie jest częścią dynamicznych właściwości węzła dom.
John Haugeland,
1
Naprawdę nie ma znaczenia, czy użyjesz tutaj klasy czy stylu ... wydajesz się bardzo zmęczony.
Brigand
2
Korzystanie z klasy jest szybsze o kilka rzędów wielkości. Dobrze wiedzieć.
Jason Rice,
1
Można po prostu użyć nazw klas warunkowych z: github.com/JedWatson/classnames
backdesk
7

Najlepsza praktyka znajduje się poniżej, zgodnie z dokumentacją:

{this.state.showFooter && <Footer />}

Renderuj element tylko wtedy, gdy stan jest poprawny.

Dynamiczny
źródło
Ta odpowiedź została już podana rok wcześniej, więc możesz ją teraz usunąć.
Dan Dascalescu
5
class Toggle extends React.Component {
  state = {
    show: true,
  }

  render() {
    const {show} = this.state;
    return (
      <div>
        <button onClick={()=> this.setState({show: !show })}>
          toggle: {show ? 'show' : 'hide'}
        </button>    
        {show && <div>Hi there</div>}
      </div>
     );
  }
}
sgr
źródło
4
   class FormPage extends React.Component{
      constructor(props){
           super(props);
           this.state = {
             hidediv: false
           }
      }

     handleClick = (){
       this.setState({
          hidediv: true
        });
      }

      render(){
        return(
        <div>
          <div className="date-range" hidden = {this.state.hidediv}>
               <input type="submit" value="Search" onClick={this.handleClick} />
          </div>
          <div id="results" className="search-results" hidden = {!this.state.hidediv}>
                        Some Results
           </div>
        </div>
        );
      }
  }
Akanksha gore
źródło
4

Zaczynam od stwierdzenia zespołu React:

W React możesz tworzyć odrębne komponenty, które zawierają potrzebne zachowanie. Następnie możesz renderować tylko niektóre z nich, w zależności od stanu twojej aplikacji.

Renderowanie warunkowe w React działa w taki sam sposób, jak warunki działają w JavaScript. Użyj operatorów JavaScript, takich jak if lub operator warunkowy, aby utworzyć elementy reprezentujące bieżący stan i pozwól React zaktualizować interfejs użytkownika, aby je dopasować.

Zasadniczo musisz pokazać komponent po kliknięciu przycisku, możesz to zrobić na dwa sposoby, używając czystego React lub CSS, używając czystego React, możesz zrobić coś takiego jak poniższy kod w twoim przypadku, więc przy pierwszym uruchomieniu wyniki nie pokazując jak hideResultsjest true, ale klikając na przycisk, zmiany gonna państwowej i hideResultsjest falsei get składnik świadczonych ponownie z nowymi warunkami wartości, to jest bardzo powszechne stosowanie zmianę widoku komponentu w React ...

var Search = React.createClass({
  getInitialState: function() {
    return { hideResults: true };
  },

  handleClick: function() {
    this.setState({ hideResults: false });
  },

  render: function() {
    return (
      <div>
        <input type="submit" value="Search" onClick={this.handleClick} />
        { !this.state.hideResults && <Results /> }
      </div> );
  }

});

var Results = React.createClass({
  render: function() {
    return (
    <div id="results" className="search-results">
      Some Results
    </div>);
   }
});

ReactDOM.render(<Search />, document.body);

Jeśli chcesz dalej studiować renderowanie warunkowe w React, zajrzyj tutaj .

Alireza
źródło
1
to powinien być najbardziej elegancki sposób!
piąty
4

Prosty przykład ukryj / pokaż za pomocą React Hooks: (srry about no fiddle)

const Example = () => {

  const [show, setShow] = useState(false);

  return (
    <div>
      <p>Show state: {show}</p>
      {show ? (
        <p>You can see me!</p>
      ) : null}
      <button onClick={() => setShow(!show)}>
    </div>
  );

};

export default Example;
StefanBob
źródło
2
prościej jest po prostu {pokazać? 1: 2}
Piotr Żak
3

Jeśli chcesz zobaczyć, jak PRZEŁĄCZYĆ wyświetlanie komponentu, sprawdź to skrzypce.

http://jsfiddle.net/mnoster/kb3gN/16387/

var Search = React.createClass({
    getInitialState: function() {
        return { 
            shouldHide:false
        };
    },
    onClick: function() {
        console.log("onclick");
        if(!this.state.shouldHide){
            this.setState({
                shouldHide: true 
            })
        }else{
                    this.setState({
                shouldHide: false 
            })
        }
    },
render: function() {
    return (
      <div>
        <button onClick={this.onClick}>click me</button>
        <p className={this.state.shouldHide ? 'hidden' : ''} >yoyoyoyoyo</p>
      </div>
    );
}
});

ReactDOM.render( <Search /> , document.getElementById('container'));
Nicholas Porter
źródło
3

Prosta metoda wyświetlania / ukrywania elementów w React przy użyciu haków

const [showText, setShowText] = useState(false);

Dodajmy teraz logikę do naszej metody renderowania:

{showText && <div>This text will show!</div>}

I

onClick={() => setShowText(!showText)}

Dobra robota.

superup
źródło
2

W niektórych przypadkach przydatny może być komponent wyższego rzędu:

Utwórz komponent wyższego rzędu:

export var HidableComponent = (ComposedComponent) => class extends React.Component {
    render() {
        if ((this.props.shouldHide!=null && this.props.shouldHide()) || this.props.hidden)
            return null;
        return <ComposedComponent {...this.props}  />;
    }
};

Rozszerz swój własny komponent:

export const MyComp= HidableComponent(MyCompBasic);

Następnie możesz użyć tego w następujący sposób:

<MyComp hidden={true} ... />
<MyComp shouldHide={this.props.useSomeFunctionHere} ... />

Zmniejsza to nieco klepsydrę i wymusza przestrzeganie konwencji nazewnictwa, jednak należy pamiętać, że MyComp będzie nadal tworzony - utworzono sposób pominięcia:

{ !hidden && <MyComp ... /> }

Vinga
źródło
1

Użyj modułu rc-if-else

npm install --save rc-if-else
import React from 'react';
import { If } from 'rc-if-else';

class App extends React.Component {
    render() {
        return (
            <If condition={this.props.showResult}>
                Some Results
            </If>
        );
    }
}
qinyuanbin
źródło
1

Użyj ref i manipuluj CSS

Jednym ze sposobów może być użycie React refi manipulowanie klasą CSS za pomocą interfejsu API przeglądarki. Jego zaletą jest unikanie ponownego wysyłania w React, jeśli jedynym celem jest ukrycie / pokazanie elementu DOM po kliknięciu przycisku.

// Parent.jsx
import React, { Component } from 'react'

export default class Parent extends Component {
    constructor () {    
        this.childContainer = React.createRef()
    }

    toggleChild = () => {
        this.childContainer.current.classList.toggle('hidden')
    }

    render () {
        return (
            ...

            <button onClick={this.toggleChild}>Toggle Child</button>
            <div ref={this.childContainer}>
                <SomeChildComponent/>
            </div>

            ...
        );
    }
}


// styles.css
.hidden {
    display: none;
}

PS Popraw mnie, jeśli się mylę. :)

UtkarshPramodGupta
źródło
Utworzono przykład codeandbox.io, tutaj: utgzx.csb.app , kod znajduje się na codandandbox.io/embed/react-show-hide-hith-css-utgzx
PatS
0

Jeśli używasz bootstrap 4, możesz w ten sposób ukryć element

className={this.state.hideElement ? "invisible" : "visible"}
ThomasP1988
źródło
0

Można to również osiągnąć w ten sposób (bardzo łatwy sposób)

 class app extends Component {
   state = {
     show: false
   };
 toggle= () => {
   var res = this.state.show;
   this.setState({ show: !res });
 };
render() {
  return(
   <button onClick={ this.toggle }> Toggle </button>
  {
    this.state.show ? (<div> HELLO </div>) : null
  }
   );
     }
basitmir
źródło
Proszę przeczytać o ustawianiu „stanu na podstawie poprzedniego stanu” na reagjs.org/docs/react-component.html#setstate . Byłoby również miło naprawić wcięcie na końcu.
Dan Dascalescu
0

ten przykład pokazuje, jak można przełączać się między komponentami za pomocą przełącznika, który przełącza się co 1 sekundę

import React ,{Fragment,Component} from "react";
import ReactDOM from "react-dom";

import "./styles.css";

const Component1 = () =>(
  <div>
    <img 
src="https://i.pinimg.com/originals/58/df/1d/58df1d8bf372ade04781b8d4b2549ee6.jpg" />
   </div>
)

const Component2 = () => {
  return (
    <div>
       <img 
src="http://www.chinabuddhismencyclopedia.com/en/images/thumb/2/2e/12ccse.jpg/250px- 
12ccse.jpg" />
  </div>
   )

 }

 class App extends Component {
   constructor(props) {
     super(props);
    this.state = { 
      toggleFlag:false
     }
   }
   timer=()=> {
    this.setState({toggleFlag:!this.state.toggleFlag})
  }
  componentDidMount() {
    setInterval(this.timer, 1000);
   }
  render(){
     let { toggleFlag} = this.state
    return (
      <Fragment>
        {toggleFlag ? <Component1 /> : <Component2 />}
       </Fragment>
    )
  }
}


const rootElement = document.getElementById("root");
ReactDOM.render(<App />, rootElement);
Snivio
źródło
O co chodzi z dziwnym adresem URL obrazu? Możesz użyć standardowej usługi zastępczej obrazu, takiej jak placeimg.com
Dan Dascalescu,
0

Użyj tej szczupłej i krótkiej składni:

{ this.state.show && <MyCustomComponent /> }
Zain Ul Hassan
źródło
Być może możesz rozwinąć składnię lean i short, aby wyjaśnić, jak to działa. Och, czekaj, zrobiono to w odpowiedzi 3 lata wcześniej . Co twoja odpowiedź znów przynosi do stołu?
Dan Dascalescu
0

Oto proste, skuteczne i najlepsze rozwiązanie z Bezklasowym Reaktorem do pokazywania / ukrywania elementów. Korzystanie z React-Hooks, które jest dostępne w najnowszym projekcie tworzenia aplikacji React, który wykorzystuje React 16

import React, {useState} from 'react';
function RenderPara(){
const [showDetail,setShowDetail] = useState(false);

const handleToggle = () => setShowDetail(!showDetail);

return (
<React.Fragment>
    <h3>
        Hiding some stuffs 
    </h3>
    <button onClick={handleToggle}>Toggle View</button>
   {showDetail && <p>
        There are lot of other stuffs too
    </p>}
</React.Fragment>)

}  
export default RenderPara;

Happy Coding :)

Remi Prasanna
źródło
0
//use ternary condition

{ this.state.yourState ? <MyComponent /> : null } 

{ this.state.yourState && <MyComponent /> }

{ this.state.yourState == 'string' ? <MyComponent /> : ''}

{ this.state.yourState == 'string' && <MyComponent /> }

//Normal condition

if(this.state.yourState){
 return <MyComponent />
}else{
  return null;
}
Naved Khan
źródło
-1

Możesz użyć pliku css

    var Results = React.createClass({
    render: function() {
        return (
            <div id="results" className={`search-results ${this.state.showResults ? 'show' : ''}`}>
                Some Results
            </div>
        );
    }
})

oraz w pliku css

    .search-results {
     ...
     display: none
     &.show {
      display: block
   }
}
arco
źródło
-1
var Search= React.createClass({
 getInitialState: () => { showResults: false },
 onClick: () => this.setState({ showResults: true }),
 render: function () {
   const { showResults } = this.state;
   return (
     <div className="date-range">
       <input type="submit" value="Search" onClick={this.handleClick} />
       {showResults && <Results />}
     </div>
   );
 }
});

var Results = React.createClass({
    render: function () {
        return (
            <div id="results" className="search-results">
                Some Results
            </div>
        );
    }
});

React.renderComponent(<Search /> , document.body);
Alan Paul Mathew
źródło
1
Czy możesz wyjaśnić, co zrobiłeś i dlaczego jest to lepsze niż zaakceptowana odpowiedź?
Seblor,
-1
class App extends React.Component {
  state = {
    show: true
  };

  showhide = () => {
    this.setState({ show: !this.state.show });
  };

  render() {
    return (
      <div className="App">
        {this.state.show && 
          <img src={logo} className="App-logo" alt="logo" />
        }
        <a onClick={this.showhide}>Show Hide</a>
      </div>
    );
  }
}
Mohammad Golkar
źródło
Czy możesz dodać wyjaśnienie dla lepszego zrozumienia? Dzięki!
Shanteshwar Inde,
@ShanteshwarInde: kopiuje ten sam pomysł z poprzedniej odpowiedzi , w tym nieprawidłowe użycie setState w zależności od bieżącego stanu. Zobacz reagjs.org/docs/react-component.html#setstate : „Jeśli chcesz ustawić stan w oparciu o poprzedni stan, przeczytaj o argumencie aktualizującym”.
Dan Dascalescu
-1

var Search = React.createClass({
    getInitialState: function() {
        return { showResults: false };
    },
    onClick: function() {
        this.setState({ showResults: true });
    },
    render: function() {
        return (
            <div>
                <input type="checkbox" value="Search" onClick={this.onClick} />
                { this.state.showResults ? <Results /> : null }
            </div>
        );
    }
});

var Results = React.createClass({
    render: function() {
        return (
            <div id="results" className="search-results">
                <input type="text" />
            </div>
        );
    }
});

ReactDOM.render( <Search /> , document.getElementById('container'));
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.6.2/react.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/15.6.2/react-dom.min.js"></script>

<div id="container">
  <!-- This element's contents will be replaced with your component. -->
</div>

Venka
źródło
4
Chociaż ten kod może odpowiedzieć na pytanie, zapewnienie dodatkowego kontekstu dotyczącego tego, dlaczego i / lub jak ten kod odpowiada na pytanie, poprawia jego długoterminową wartość.
xiawi
Co powiedział @xiawi. Ponadto używaj constzamiast vardeklarować stałe.
Dan Dascalescu