Показать или скрыть элемент реагирует

Я возиться с React.js впервые и не может найти способ показать или скрыть что-то на странице с помощью события click. Я не загружаю другую библиотеку на страницу, поэтому я ищу какой-то собственный способ использования библиотеки React. Это то, что у меня есть до сих пор. Я хотел бы показать результаты div, когда событие 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);

14 ответов


ключ должен обновить состояние компонента в обработчике щелчка с помощью setState. Когда изменения состояния применяются,render метод вызывается снова с новым состоянием:

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/


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

вот альтернативный синтаксис для тернарного оператора:

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

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

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

Lean почему


также альтернативный синтаксис с display: 'none';

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

однако, если вы злоупотребляете display: 'none', это приводит к загрязнению DOM и в конечном итоге замедляет ваше приложение.


вот мой подход с использованием 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
      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'));

демо:http://jsfiddle.net/kb3gN/16688/

лучше отображать некоторый элемент только при необходимости, а не добавлять некоторые классы css с display: none. Если вы установите display: none - элемента, оказываемых реагировать и добавил DOM - это может плохо сказаться на производительности.

представьте, что у вас есть страница с вкладками, где каждая вкладка есть много контента и где одновременно открывается только 1 вкладка. Гораздо лучше держать в DOM только те элементы, которые должны быть отображены.

в коде выше, чтобы достичь этого, я использую код, как:

{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 0.11 вы также можете просто вернуть null, чтобы не отображать контент.

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


Я создал небольшой компонент, который обрабатывает это для вас: https://www.npmjs.com/package/react-toggle-display

Он устанавливает атрибут style в display: none !important на основе hide или show бутафория.

пример использования:

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

вы устанавливаете логическое значение в состоянии (например, ' show)', а затем делаете:

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

return <div style={style}>...</div>

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

Вариант 1: условное отображение в родитель.

мне не нравится этот метод, если вы не собираетесь отображать компонент только один раз и оставить его там. Проблема в том, что react будет создавать компонент с нуля каждый раз при переключении видимости. Вот пример. LogoutButton или LoginButton условно отображаются в Родительском LoginControl. Если вы запустите это, вы заметите, что конструктор вызывается при каждом нажатии кнопки. 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')
);

теперь React довольно быстро создает компоненты с нуля. Тем не менее, он по-прежнему должен вызывать ваш код при его создании. Поэтому, если ваш конструктор, componentDidMount, render и т. д. код дорог, он значительно замедлит показ компонента. Это также означает, что вы не можете использовать это с компонентами с состоянием, где вы хотите сохранить состояние при скрытии (и восстановить при отображении.) Единица преимущество заключается в том, что скрытый компонент не создается вообще, пока он не выбран. Таким образом, скрытые компоненты не будут задерживать начальную загрузку страницы. Могут также быть случаи, когда вы хотите, чтобы компонент с состоянием сбрасывался при переключении. В таком случае это ваш лучший вариант.

Вариант 2: условное отображение в дочернем

это создает оба компонента один раз. Затем короткое замыкание остальной части кода рендеринга, если компонент скрыт. Вы можете также короткое замыкание другая логика в другом методы с использованием видимой опоры. Обратите внимание на консоль.войдите на страницу 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')
);

теперь, если логика инициализации быстрая, а дети без состояния, то вы не увидите разницы в производительности или функциональности. Однако зачем заставлять React создавать совершенно новый компонент каждый переключатель? Однако если инициализация дорогостоящая, опция 1 будет запускать ее каждый раз при переключении компонента, который будет замедляться страница вниз при переключении. Опция 2 будет запускать все inits компонента при загрузке первой страницы. Замедление первой нагрузки. Следует отметить еще раз. Если вы просто показываете компонент один раз на основе условия и не переключаете его или хотите сбросить его при toggledm, тогда Вариант 1 прекрасен и, вероятно, лучший вариант.

Если медленная загрузка страницы является проблемой, это означает, что у вас есть дорогой код в методе жизненного цикла, и это, как правило, не очень хорошая идея. Можно, наверное следует решить проблему медленной загрузки страницы, переместив дорогостоящий код из методов жизненного цикла. Переместите его в асинхронную функцию, которая запускается ComponentDidMount, и обратный вызов помещает ее в переменную состояния с setState (). Если переменная состояния равна null, а компонент виден, то функция render возвращает заполнитель. В противном случае визуализируйте данные. Таким образом, страница будет быстро загружаться и заполнять вкладки по мере их загрузки. Вы также можете переместить логику в родитель и нажать результаты для детей как реквизит. Таким образом, вы можете определить приоритеты, какие вкладки загружаются первыми. Или кэшировать результаты и запускать логику только при первом отображении компонента.

Вариант 3: Скрытие Класс

скрытие класса, вероятно, проще всего реализовать. Как уже упоминалось, вы просто создаете класс CSS с display: none и назначаете класс на основе prop. Недостатком является то, что вызывается весь код каждого скрытого компонента, и все скрытые компоненты присоединяются к DOM. (Вариант 1 вообще не создает скрытые компоненты. И Вариант 2 короткого замыкания ненужного кода, когда компонент скрыт и полностью удаляет компонент из DOM.) Похоже, это быстрее при переключении видимости в соответствии с некоторыми тестами, сделанными комментаторами на другие ответы, но я не могу говорить об этом.

Вариант 4: один компонент, но изменить реквизит. Или, может быть, вообще нет компонента и кэш HTML.

это не будет работать для каждого приложения, и это не по теме потому что речь идет не о скрытии компонентов, но это может быть лучшим решением для некоторых случаев использования, чем скрытие. Допустим, у вас есть вкладки. Возможно, можно написать один компонент React и просто использовать реквизит, чтобы изменить то, что отображается на вкладке. Вы также можете сохранить JSX для переменных состояния и использовать prop, чтобы решить, какой JSX вернуть в функцию рендеринга. Если JSX должен быть сгенерирован, сделайте это и кэшируйте его в родителе и отправьте правильный в качестве опоры. Или генерировать в ребенке и кэшируйте его в состоянии ребенка и используйте реквизит для выбора активного.


это хороший способ использовать виртуальный DOM:

реагировать:

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

Скрипка здесь


Если вы хотите увидеть, как переключить отображение компонента проверки этой скрипки.

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

в некоторых случаях может быть полезен компонент более высокого порядка:

создать компонент более высокого порядка:

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}  />;
    }
};

расширить свой собственный компонент:

export const MyComp= HidableComponent(MyCompBasic);

тогда вы можете использовать его следующим образом:

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

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

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


я начинаю с этого заявления от команды React:

в React можно создавать отдельные компоненты, инкапсулирующие поведение тебе нужно. Затем вы можете отобразить только некоторые из них, в зависимости от состояние вашего приложения.

условный рендеринг в React работает так же, как условия работы в Яваскрипт. Используйте операторы JavaScript, такие как if или conditional оператор для создания элементов, представляющих текущее состояние, и пусть React update пользовательский интерфейс, чтобы соответствовать им.

вам в основном нужно показать компонент при нажатии кнопки, вы можете сделать это двумя способами, используя pure React или CSS, используя pure React way, вы можете сделать что-то вроде кода ниже в вашем случае, поэтому в первом запуске результаты не отображаются как hideResults is true, но, нажав на кнопку, состояние изменится и hideResults is false и компонент снова отображается с новыми условиями значения, это очень распространенное использование изменения представление компонента в 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);

если вы хотите продолжить изучение условного рендеринга в React, посмотрите здесь.


рекомендуется ниже, в соответствии с документацией:

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

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


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