在 React 中显示或隐藏元素

IT技术 javascript reactjs
2021-01-24 17:50:47

我第一次使用 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);
6个回答

大约在 2020 年做出react

onClick回调中,调用状态钩子的setter 函数更新状态并重新渲染:

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

大约 2014 年的react

关键是使用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's contents will be replaced with your component. -->
</div>

JSFiddle

而不是{ showResults ? <Results /> : null }可以做{ showResults && <Results /> }
2021-03-14 17:50:47
我认为 Johns 的评论需要审核。我采用了预期的答案,这很简洁,“感觉”更像反应。但是,我无法在未安装的组件上设置初始状态和任何有用的东西。我正在考虑使用 css 来隐藏东西。未安装组件上的侦听器将默默地失败,这让我今天损失了很多时间。
2021-03-25 17:50:47
这是否意味着当样式更改(设置为显示/隐藏)时,react 会重新渲染组件!?
2021-03-31 17:50:47
如另一个答案中所述,插入/删除比简单的类屏蔽慢得多。
2021-04-03 17:50:47
是的,关于状态与道具的好点。一个更好的方法是在这里的教程中,其中搜索栏和结果表是兄弟姐妹,而不是将结果放在搜索中:facebook.github.io/react/docs/thinking-in-react.html
2021-04-07 17:50:47
<style type="text/css">
    .hidden { display:none; }
</style>
const Example = props => 
  <div className={props.shouldHide? 'hidden' : undefined}>Hello</div>
“通过添加/删除来保证回流”——不是绝对定位的元素,这就是 Famous 获得令人难以置信的性能的方式。但是你在指标上提出了一个有效的观点。
2021-03-13 17:50:47
所以我只是测试了返回 null 与设置一个具有 161 个相当大的 dom 节点的隐藏类。使用类比删除节点要快得多。
2021-03-17 17:50:47
最好像道格拉斯的回答那样有条件地返回 null 。这允许 React 完全从 DOM 中删除它。在您的情况下,div 及其内容仍在 DOM 中,只是没有显示。这可能会影响性能。
2021-04-01 17:50:47
对于它的value,这里的反应文档中提到了这一点:facebook.github.io/react/docs/...
2021-04-07 17:50:47
添加和删​​除 dom 元素的性能影响比隐藏和显示它的性能影响要糟糕得多。我知道他的方法和我的不同,我相信你完全错了。请考虑花时间定义“性能影响”,然后对其进行衡量。
2021-04-08 17:50:47

这是三元运算符的另一种语法:

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

相当于:

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

了解原因


也可以使用替代语法 display: 'none';

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

但是,如果您过度使用display: 'none',这会导致 DOM 污染并最终减慢您的应用程序。

第二个例子是代码异味,在我看来
2021-03-12 17:50:47
这在任何意义上都不是“三元运算符的替代语法”。这是有问题的,除了对开头子句的双重否定之外,还有其他地方会导致问题。
2021-03-13 17:50:47
警告!仅对布尔值使用“双与号(&&)”方法。{ this.state.myComponents.length && <MyComponent /> } 将呈现 0,如果 myComponents 为空数组(例如)
2021-03-30 17:50:47
@MegaProger 在这种情况下使用!!ie 转换为布尔值{ !!this.state.myComponents.length && <MyComponent /> }
2021-03-30 17:50:47

这是我的方法。

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

在上面的代码中,为了实现这一点,我使用了如下代码:

{opened && <SomeElement />}

SomeElement仅当opened为 true 时才会呈现它之所以起作用,是因为 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 (and false will be ignored by react during rendering)
// be careful with 'falsy' values eg
const someValue = [];
someValue.length && <SomeElement /> // will output 0, which will be rednered by react
// it'll be better to:
someValue.length > 0 && <SomeElement /> // will render nothing as we cast the value to boolean

使用这种方法而不是 CSS 'display: none' 的原因;

  • 虽然用 CSS 隐藏元素可能“更便宜” - 在这种情况下,“隐藏”元素在react世界中仍然“活跃”(这可能使它实际上更昂贵)
    • 这意味着如果父元素的props(例如<TabView>)发生变化 - 即使您只看到一个选项卡,所有 5 个选项卡都会重新呈现
    • 隐藏元素可能仍然有一些生命周期方法在运行 - 例如。它可能会在每次更新后从服务器获取一些数据,即使它不可见
    • 如果隐藏元素接收到不正确的数据,它可能会导致应用程序崩溃。可能会发生这种情况,因为您可以在更新状态时“忘记”不可见的节点
    • 在使元素可见时,您可能会错误地设置错误的“显示”样式 - 例如。某些 div 默认为 'display: flex',但您会错误地设置 'display: block',display: invisible ? 'block' : 'none'这可能会破坏布局
    • usingsomeBoolean && <SomeNode />非常容易理解和推理,尤其是当您与显示或不显示相关的逻辑变得复杂时
    • 在许多情况下,您希望在元素重新出现时“重置”它。例如。您可能有一个滑块,每次显示时都希望将其设置为初始位置。(如果这是保持先前元素状态的理想行为,即使它是隐藏的,IMO 很少见 - 如果以不同的方式记住这个状态会很复杂,我确实会考虑使用 CSS)
@neiya 我没有。CSS 可能在处理小元素时性能更高,但通常您希望渲染可选的大部分内容,例如。标签。此外,虽然某些元素被 CSS 隐藏了 - 它在反应世界中仍然存在。这意味着它可能会更新它的状态,获取一些数据等,这可能会很昂贵并导致意外行为。实际上,IMO 实施起来非常简单。
2021-03-11 17:50:47
这是一个很好的例子!一件小事, boxContent 应该是 className="boxContent"
2021-03-25 17:50:47
这里有一个错误:this.setState({isOpened: !isOpened});修改状态时不要依赖状态本身。这是一个很好的例子:reactjs.org/docs/...所以它应该是:this.setState( s => ({isOpened: !s.isOpened}) ). 注意 setState 中的箭头函数。
2021-03-25 17:50:47
您是否有任何来源/基准/示例确认“如果您设置 display: none - 元素仍然由 react 呈现并添加到 DOM - 这可能会对性能产生不良影响。” ?
2021-04-10 17:50:47

使用最新版本 react 0.11,您也可以只返回 null 以不呈现任何内容。

渲染为空

请更新以包含解决 OP 问题的“所需的确切代码”示例,如 SO 指南中所述。
2021-03-17 17:50:47
仅链接回复应作为评论发布,而不是“答案”。为了有资格作为答案,请包含链接页面中的相关信息。如果页面无法访问,或者其内容发生更改,则此响应将变得无用。SO 上的所有答案都必须是自给自足的,不需要外部资源来阅读解决方案。如果问题属于适合编码答案的类型,那么解决问题所需的确切代码必须嵌入到答案中。
2021-03-23 17:50:47