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

Я впервые общаюсь с 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);

Ответ 1

Ключ в том, чтобы обновить состояние компонента в обработчике setState используя 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'));
<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 contents will be replaced with your component. -->
</div>

Ответ 2

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

Ответ 3

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

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

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

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

Lean why


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

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

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

Ответ 4

Вот мой подход с использованием 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() {
    this.setState(oldState => ({ isOpened: !oldState.isOpened }));
  }

  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 - это может плохо повлиять на производительность.

Представьте, что у вас есть страница с вкладками, где на каждой вкладке много контента и только одна вкладка открывается одновременно. Гораздо лучше держать в 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

Ответ 5

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

Рендеринг в ноль

Ответ 6

Я создал небольшой компонент, который обрабатывает это для вас: response-toggle-display

Он устанавливает атрибут стиля на 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);

Ответ 7

Вы устанавливаете логическое значение в состоянии (например, "показать" ), а затем выполните:

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

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

Ответ 8

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

Вариант 1: Условное рендеринг в родительском.

Мне не нравится этот метод, если вы не собираетесь отображать компонент один раз и оставить его там. Проблема в том, что это вызовет реакцию на создание компонента с нуля каждый раз при переключении видимости. Вот пример. 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 довольно быстро создает компоненты с нуля. Тем не менее, он все равно должен вызывать ваш код при его создании. Поэтому, если ваш конструктор, компонентDidMount, рендеринг и т.д. Дорогой, то он значительно замедлит показ компонента. Это также означает, что вы не можете использовать это с компонентами с состоянием, в которых вы хотите сохранить состояние при скрытии (и восстанавливаться при отображении). Одно из преимуществ заключается в том, что скрытый компонент вообще не создается до его выбора. Таким образом, скрытые компоненты не будут задерживать вашу начальную загрузку страницы. Могут также быть случаи, когда вы хотите, чтобы компонент состояния был сброшен при переключении. В этом случае это ваш лучший вариант.

Вариант 2: Условный рендеринг у ребенка

Это создает оба компонента один раз. Затем замыкает остальную часть кода визуализации, если компонент скрыт. Вы также можете закорачивать другую логику другими способами, используя видимую опору. Обратите внимание на console.log на странице 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 создает абсолютно новый компонент, который все равно переключается? Если инициализация стоит дорого, Option 1 будет запускать ее каждый раз, когда вы переключаете компонент, который замедляет страницу при переключении. Вариант 2 будет запускать все компоненты для загрузки первой страницы. Замедление этой первой нагрузки. Следует отметить еще раз. Если вы просто показываете компонент один раз на основе состояния, а не переключая его, или вы хотите, чтобы он сбросился при переходе на него, то вариант 1 является прекрасным и, вероятно, лучшим вариантом.

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

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

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

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

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

Ответ 9

Это хороший способ использовать виртуальный 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;
}

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

Ответ 10

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

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

Отображать элемент только тогда, когда состояние является действительным.

Ответ 11

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

Ответ 12

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

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

Ответ 13

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

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

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

По сути, вам нужно показать компонент при нажатии кнопки, вы можете сделать это двумя способами, используя чистый React или CSS, используя чистый React способ, вы можете сделать что-то вроде приведенного ниже кода в вашем случае, так что при первом запуске, результаты не отображаются, поскольку hideResults имеет значение true, но при нажатии на кнопку состояние изменится, а hideResults будет hideResults 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, посмотрите здесь.

Ответ 14

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

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

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

Ответ 15

Если вы используете bootstrap 4, вы можете скрыть элемент таким образом

className={this.state.hideElement ? "invisible" : "visible"}

Ответ 16

Это также может быть достигнуто так (очень простой способ)

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

Ответ 17

Используйте модуль 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>
        );
    }
}

Ответ 18

Используйте этот простой и короткий синтаксис:

{ this.state.show && <MyCustomComponent /> }

Ответ 19

  Используйте ref и манипулируйте CSS

Одним из способов может быть использование React ref и манипулирование классом CSS с помощью API браузера. Его преимущество заключается в том, чтобы избежать повторного рендеринга в React, если единственная цель - скрыть/показать какой-либо элемент DOM одним нажатием кнопки.

// 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 Поправь меня, если я ошибаюсь. :)

Ответ 20

В этом примере показано, как можно переключаться между компонентами с помощью переключателя, который переключается через каждые 1 с.

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

Ответ 21

Вы можете использовать файл CSS

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

и в файле CSS

    .search-results {
     ...
     display: none
     &.show {
      display: block
   }
}

Ответ 22

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

Ответ 23

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

Ответ 24

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 contents will be replaced with your component. -->
</div>