在React中显示或隐藏元素

时间:2014-07-01 05:17:00

标签: javascript reactjs

我第一次搞乱React.js,找不到通过点击事件在页面上显示或隐藏某些内容的方法。我没有加载任何其他库到页面,所以我正在寻找一些使用React库的本地方式。这就是我到目前为止所拥有的。我想在点击事件触发时显示结果div。

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

29 个答案:

答案 0 :(得分:422)

关键是使用setState更新点击处理程序中组件的状态。应用状态更改后,将使用新状态再次调用render方法:

&#13;
&#13;
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'));
&#13;
<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>
&#13;
&#13;
&#13;

JSFiddle

答案 1 :(得分:175)

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

答案 2 :(得分:90)

以下是三元运算符的替代语法:

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

相当于:

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

Lean why

display: 'none';

的替代语法
<MyComponent style={this.state.showMyComponent ? {} : { display: 'none' }} />

但是,如果过度使用display: 'none',这会导致DOM污染并最终降低您的应用速度。

答案 3 :(得分:43)

这是我使用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/

最好只在需要时渲染一些元素,而不是添加一些display: none的css类。如果设置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

答案 4 :(得分:15)

最新版本的反应为0.11,您也可以返回null以不呈现内容。

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

答案 5 :(得分:10)

我创建了一个小组件来处理这个问题:https://www.npmjs.com/package/react-toggle-display

它根据display: none !importanthide道具将样式属性设置为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);

答案 6 :(得分:8)

您在状态中设置了一个布尔值(例如&#39;显示)&#39;,然后执行:

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

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

答案 7 :(得分:7)

使用钩子在React中显示/隐藏元素的简单方法

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

现在,让我们在渲染方法中添加一些逻辑:

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

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

干得好。

答案 8 :(得分:7)

已经有几个很好的答案,但我认为它们的解释并不是很好,并且给出的一些方法包含一些可能会让人感到震惊的问题。因此,我将讨论三种主要方式(加上一个非主题选项),并解释其优缺点。我主要是写这个,因为选项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从头开始创建组件非常快。但是,它仍然需要在创建时调用您的代码。因此,如果您的构造函数,componentDidMount,render等代码很昂贵,那么它将显着减慢显示组件的速度。这也意味着你不能在有状态的组件中使用它,你希望隐藏状态时保存状态(并在显示时恢复)。一个优点是隐藏的组件在被选中之前根本不会被创建。因此隐藏的组件不会延迟您的初始页面加载。在切换时,可能还有一些情况需要重置有状态组件。在这种情况下,这是您最好的选择。

选项2:孩子的条件渲染

这会创建两个组件一次。如果隐藏组件,则将其余的渲染代码短路。您还可以使用可见道具在其他方法中将其他逻辑短路。注意codepen页面中的console.log。 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将在首页加载时运行所有组件的内容。放慢第一次加载。应该再说一遍。如果您只是根据条件显示组件一次并且没有切换它,或者您希望它在切换时重置,那么选项1很好,可能是最佳选择。

如果慢页面加载是一个问题,那么这意味着你在生命周期方法中得到了昂贵的代码,这通常不是一个好主意。您可以并且可能应该通过将昂贵的代码移出生命周期方法来解决缓慢的页面加载问题。将其移动到由ComponentDidMount启动的异步函数,并使回调将其置于具有setState()的状态变量中。如果state变量为null并且组件可见,则让render函数返回占位符。否则渲染数据。这样,页面将快速加载并在加载时填充选项卡。您还可以将逻辑移动到父级中,并将结果作为道具推送给子级。这样,您可以优先考虑首先加载哪些选项卡。或者缓存结果,并且只在第一次显示组件时运行逻辑。

选项3:隐藏课程

类隐藏可能是最容易实现的。如上所述,您只需使用display:none创建一个CSS类,并根据prop分配类。缺点是调用每个隐藏组件的整个代码,并将所有隐藏组件附加到DOM。 (选项1根本不会创建隐藏的组件。当组件被隐藏时,选项2会短路不必要的代码并完全从DOM中删除组件。)根据评论者的一些测试,这似乎更快地切换可见性。其他答案,但我不能说。

选项4:一个组件但改变道具。或者根本没有组件并缓存HTML。

这个不适用于每个应用程序,并且它不在主题,因为它不是隐藏组件,但它可能是一些用例比隐藏更好的解决方案。假设你有标签。可以编写一个React Component并只使用props来更改选项卡中显示的内容。您还可以将JSX保存到状态变量并使用prop来决定在render函数中返回哪个JSX。如果必须生成JSX,那么执行它并将其缓存在父级中,并将正确的一个作为prop发送。或者在子项中生成并将其缓存在子项的状态中,并使用props来选择活动状态。

答案 9 :(得分:5)

这是一种使用虚拟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;
}

小提琴here

答案 10 :(得分: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>
     );
  }
}

答案 11 :(得分: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>
        );
      }
  }

答案 12 :(得分:3)

如果你想看看如何切换这个小提琴组件的显示器。

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 :(得分:3)

我从React团队的声明开始:

  

在React中,您可以创建封装行为的不同组件   你需要。然后,您可以只渲染其中一些,具体取决于   申请状态。

     

React中的条件渲染与条件的工作方式相同   JavaScript的。使用像if或条件的JavaScript运算符   operator创建表示当前状态的元素,并让   React更新UI以匹配它们。

你基本上需要在单击按钮时显示组件,你可以通过两种方式来做,使用纯React或使用CSS,使用纯React方式,你可以在你的情况下执行类似下面的代码,所以在第一个运行时,结果未显示hideResultstrue,但是点击该按钮,状态将发生变化,hideResultsfalse,新组件将再次呈现值条件,这是在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中进一步研究条件渲染,请查看here

答案 14 :(得分:2)

在某些情况下,更高阶的组件可能有用:

创建更高阶的组件:

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 :(得分:1)

这也可以这样实现(非常简单)

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

答案 16 :(得分:1)

  

使用 ref 并操作CSS

一种方法可能是使用React的ref并使用浏览器的API操纵CSS类。如果这样做的唯一目的是在单击按钮时隐藏/显示某些DOM元素,则它的好处是避免在React中重新渲染。

// 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 如果我错了,请纠正我。 :)

答案 17 :(得分:1)

使用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 :(得分:0)

您可以使用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
   }
}

答案 19 :(得分:0)

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

答案 20 :(得分:0)

使用这种简洁的语法:

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

答案 21 :(得分:0)

这里提供了一个简单,有效和最佳的解决方案,该解决方案带有无类React组件,用于显示/隐藏元素。使用 React-Hooks (在最新的 create-react-app 项目中可用),该项目使用 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;

快乐编码:)

答案 22 :(得分: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;
}

答案 23 :(得分:0)

此示例显示了如何通过使用每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);

答案 24 :(得分:0)

如果您使用引导程序4,则可以用这种方式隐藏元素

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

答案 25 :(得分:0)

我能够使用CSS属性“隐藏”。不知道可能的缺点。

export default function App() {
    const [hidden, setHidden] = useState(false);
    return (
      <div>
        <button onClick={() => setHidden(!hidden)}>HIDE</button>
        <div hidden={hidden}>hidden component</div>
      </div>
    );
  }

答案 26 :(得分:0)

// Try this way

class App extends Component{

  state = {
     isActive:false
  }

  showHandler = ()=>{
      this.setState({
          isActive: true
      })
  }

  hideHandler = () =>{
      this.setState({
          isActive: false
      })
  }

   render(){
       return(
           <div>
           {this.state.isActive ? <h1>Hello React jS</h1> : null }
             <button onClick={this.showHandler}>Show</button>
             <button onClick={this.hideHandler}>Hide</button>
           </div>
       )
   }
}

答案 27 :(得分:-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>
    );
  }
}

答案 28 :(得分:-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>