Pokaż lub ukryj element w Reaccie

Bawię się z Reactem.js po raz pierwszy i nie może znaleźć sposobu, aby pokazać lub ukryć coś na stronie za pomocą zdarzenia kliknięcia. Nie Ładuję żadnej innej biblioteki na stronę, więc szukam jakiegoś natywnego sposobu korzystania z biblioteki Reacta. To jest to, co mam do tej pory. Chciałbym pokazać wyniki div przy wywołaniu zdarzenia click.

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);
Author: Damjan Pavlica, 2014-07-01

14 answers

Kluczem jest zaktualizowanie stanu komponentu w programie obsługi kliknięć za pomocą setState. Gdy stan zostanie zastosowany, metoda render zostanie wywołana ponownie 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'));

Http://jsfiddle.net/kb3gN/15084/

 350
Author: Douglas,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-06-22 01:39:47
<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>
    );
}
 146
Author: John Haugeland,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-06-22 01:51:31

Oto alternatywna składnia dla operatora trójdzielnego:

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

Jest równoważne:

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

Lean why


Także składnia alternatywna z display: 'none';

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

Jednakże, jeśli nadużywasz display: 'none', prowadzi to do zanieczyszczenia DOM i ostatecznie spowalnia Twoją aplikację.

 67
Author: Lyubomir,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-10-10 12:35:50

Oto moje podejście do ES6. Chociaż zaakceptowana odpowiedź jest poprawna, jest dość przestarzała.

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
      isOpened: 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 { isOpened } = this.state;
    this.setState({
      // toggle value of `opened`
      isOpened: !opened,
    });
  }

  render() {
    const { title, children } = this.props;
    const { isOpened } = this.state;
    return (
      <div className="box">
        <div className="boxTitle" onClick={this.toggleBox}>
          {title}
        </div>
        {isOpened && children && (
          <div className="boxContent">
            {children}
          </div>
        )}
      </div>
    );
  }
}

ReactDOM.render((
  <ToggleBox title="Click me">
    <div>Some content</div>
  </ToggleBox>
), document.getElementById('app'));

Demo: http://jsfiddle.net/kb3gN/16688/

Lepiej renderować jakiś element tylko w razie potrzeby, niż dodawać jakieś klasy css z display: none. Jeśli ustawisz display: none - element jest nadal renderowany przez Reacta i dodany do DOM - może to mieć zły wpływ na wydajność.

Wyobraź sobie, że masz stronę z zakładkami, gdzie każda zakładka ma dużo treści i gdzie jest tylko 1 Zakładka natychmiast otwarte. Znacznie lepiej trzymać w DOM tylko te elementy, które mają być wyświetlane.

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

{opened && <SomeElement />}

To wyrenderuje SomeElement tylko wtedy, gdy opened jest prawdziwe. Działa to 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
 26
Author: pie6k,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-06-20 14:03:00

Z najnowszą wersją Reacta 0.11 możesz również zwrócić null, aby zawartość nie była renderowana.

Https://facebook.github.io/react/blog/2014/07/13/react-v0.11-rc1.html#rendering-to-null

 14
Author: squiddle,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-07-18 16:54:11

Stworzyłem mały komponent, który obsługuje to dla Ciebie: https://www.npmjs.com/package/react-toggle-display

Ustawia atrybut style na display: none !important na podstawie właściwości hide lub show.

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);
 9
Author: ccnokes,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-06-21 22:20:58

Ustawiasz wartość logiczną w stanie (np. ' show)', a następnie wykonujesz:

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

return <div style={style}>...</div>
 7
Author: FakeRainBrigand,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-07-01 05:30:24

Istnieje już kilka świetnych odpowiedzi, ale nie sądzę, aby zostały one dobrze wyjaśnione i kilka z podanych metod zawiera kilka gotchas, które mogą potknąć ludzi. Więc mam zamiar przejść nad trzema głównymi sposobami (plus jedną opcję off-topic), aby to zrobić i wyjaśnić za i przeciw. Piszę to głównie dlatego, że opcja 1 była bardzo polecana i istnieje wiele potencjalnych problemów z tą opcją, jeśli nie jest używana poprawnie.

Opcja 1: renderowanie warunkowe w rodzic.

Nie podoba mi się ta metoda, chyba że masz zamiar renderować komponent tylko raz i zostawić go tam. Problem polega na tym, że react stworzy komponent od podstaw za każdym razem, gdy przełączysz widoczność. Oto przykład. LogoutButton lub LoginButton są warunkowo renderowane w rodzicu LoginControl. Jeśli uruchomisz to 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 jest dość szybki w tworzeniu komponentów od zera. Jednak nadal musi wywoływać Twój kod podczas jego tworzenia. Więc jeśli twój konstruktor, kod componentDidMount, render itp. jest drogi, to znacznie spowolni wyświetlanie komponentu. Oznacza to również, że nie można tego używać z komponentami stanu, w których stan ma być zachowany po ukryciu (i przywrócony po wyświetleniu).) Jedyną zaletą jest że ukryty komponent nie zostanie utworzony, dopóki nie zostanie wybrany. Tak więc ukryte komponenty nie opóźnią początkowego ładowania strony. Mogą również wystąpić przypadki, w których komponent Stanowy ma zostać zresetowany po włączeniu. W takim przypadku jest to najlepsza opcja.

Opcja 2: renderowanie warunkowe w potomku

To tworzy oba komponenty raz. Następnie powoduje zwarcie reszty kodu renderującego, jeśli komponent jest ukryty. Można również zwarć inne logiki w innych metodach za pomocą widoczny rekwizyt. Zwróć uwagę na konsolę.Zaloguj się 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ą bezpaństwowe, to nie zobaczysz różnicy w wydajności lub funkcjonalności. Po co jednak zmuszać Reacta do tworzenia zupełnie nowego komponentu przy każdym przełączaniu? Jeśli jednak inicjalizacja jest kosztowna, opcja 1 uruchomi ją za każdym razem, gdy przełączysz komponent, który spowolni stronę podczas przełączania. Opcja 2 uruchomi wszystkie Inity komponentu przy pierwszym załadowaniu strony. Zwolnij pierwszy ładunek. / Align = "left" / Jeśli tylko pokazujesz komponent jeden raz na podstawie warunku i nie przełączasz go, lub chcesz go zresetować podczas toggledm, to opcja 1 jest dobra i prawdopodobnie najlepsza.

Jeśli jednak powolne ładowanie strony jest problemem, oznacza to, że masz drogi kod w metodzie cyklu życia i ogólnie nie jest to dobry pomysł. Możesz i prawdopodobnie powinieneś rozwiązać problem powolnego ładowania strony przez przeniesienie kosztownego kodu z metod cyklu życia. Przenieś go do funkcji asynchronicznej, która jest uruchamiana przez ComponentDidMount, a wywołanie zwrotne umieść go w zmiennej stanu za pomocą setState(). Jeśli zmienna stanowa ma wartość null i komponent jest widoczny, Funkcja render zwraca symbol zastępczy. W przeciwnym razie Renderuj dane. W ten sposób strona ładuje się szybko i wypełnia karty podczas ładowania. Możesz także przenieść logikę do rodzica i przekazać wyniki dzieciom jako rekwizyty. Że sposób, w jaki możesz ustalić priorytety, które karty zostaną załadowane jako pierwsze. Lub buforuj wyniki i uruchom logikę tylko przy pierwszym wyświetleniu komponentu.

Opcja 3: Ukrywanie Klasy

Ukrywanie klas jest prawdopodobnie najłatwiejsze do zaimplementowania. Jak już wspomniałem, wystarczy utworzyć klasę CSS z display: none i przypisać klasę opartą na propie. Minusem jest to, że cały kod każdego ukrytego komponentu jest wywoływany i wszystkie ukryte komponenty są dołączane do DOM. (Opcja 1 w ogóle nie tworzy ukrytych komponentów. I Opcja 2 zwarcie niepotrzebnego kodu, gdy komponent jest ukryty i całkowicie usuwa komponent z DOM.) Wygląda na to, że jest to szybsze w przełączaniu widoczności według niektórych testów wykonanych przez komentatorów na inne odpowiedzi, ale nie mogę się do tego odzywać.

Opcja 4: jeden komponent, ale zmień właściwości. A może w ogóle nie ma komponentu i buforuje HTML.

Ten nie będzie działał dla każdej aplikacji i jest off topic, ponieważ nie chodzi o ukrywanie komponentów, ale może być lepszy rozwiązanie dla niektórych przypadków użycia niż ukrywanie. Powiedzmy, że masz karty. Może być możliwe napisanie jednego komponentu Reactowego i użycie właściwości do zmiany tego, co jest wyświetlane na karcie. Możesz również zapisać JSX do zmiennych stanu i użyć właściwości, aby zdecydować, który JSX ma zostać zwrócony w funkcji renderowania. Jeśli JSX ma być wygenerowany, zrób to i buforuj go w rodzicu i wyślij poprawny jako rekwizyt. Lub wygenerować w potomku i buforować go w stanie dziecka i użyć właściwości, aby wybrać aktywny jeden.

 6
Author: Kelnor,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-09-11 21:42:37

Jest to dobry sposób na wykorzystanie Wirtualnego DOM:

React:

            var Comp = React.createClass({
                getInitialState: function(){
                return {hide: false};
              },
              toggle: function(){
                this.setState({hide: !this.state.hide});
              },
              render: function() {
                return <div>
                        <button onClick={this.toggle}>toggle</button>    
                    <div className={'hide-' + this.state.hide}>Hi there</div>
                </div>;
              }
            });

            ReactDOM.render(
              <Comp />,
              document.getElementById('container')
            );

CSS

            .hide-true  {
              display: none;
            }

Fiddle here

 4
Author: daniloprates,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-07-03 17:27:20

Jeśli chcesz zobaczyć, jak włączyć wyświetlanie komponentu checkout to fiddle.

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'));
 2
Author: Nicholas,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-12-29 21:38:19

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

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);

Wtedy możesz użyć go tak:

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

Zmniejsza to nieco boilerplate i wymusza trzymanie się konwencji nazewnictwa, jednak należy pamiętać, że MyComp nadal będzie instancjonowany - sposób pominięcia został wspomniany wcześniej:

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

 1
Author: vinga,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-11-13 08:57:45

Zacznę od tego stwierdzenia od zespołu Reactowego:

W Reaccie możesz tworzyć różne komponenty, które hermetyzują zachowanie potrzebujesz. Następnie można renderować tylko niektóre z nich, w zależności od stan twojego wniosku.

Renderowanie warunkowe w Reaccie działa tak samo jak warunki w JavaScript. Użyj operatorów JavaScript, takich jak if lub conditional operator do tworzenia elementów reprezentujących bieżący stan i niech React zaktualizuje interfejs użytkownika, aby pasował oni.

W zasadzie musisz pokazać komponent, gdy przycisk zostanie kliknięty, możesz to zrobić na dwa sposoby, używając czystego Reacta lub CSS, używając czystego Reacta, możesz zrobić coś takiego jak poniższy kod w Twoim przypadku, więc w pierwszym uruchomieniu, wyniki nie są wyświetlane jako hideResults jest true, ale klikając na przycisk, Stan się zmieni i hideResults jest false i komponent zostanie renderowany ponownie z nowymi warunkami wartości, jest to bardzo powszechne użycie zmiany widoku komponentu w Reaguj...

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 przeprowadzić dalsze badania nad renderowaniem warunkowym w Reaccie, zajrzyj tutaj .

 1
Author: Alireza,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-06-16 09:42:13

Najlepsze praktyki znajdują się poniżej zgodnie z dokumentacją:

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

Renderuje element tylko wtedy, gdy stan jest poprawny.

 1
Author: Dynamic,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-05-13 07:29:56
   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>
        );
      }
  }
 1
Author: Akanksha gore,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-08-23 13:17:27