【问题标题】:How to toggle class in the nested component in ReactJS如何在 ReactJS 的嵌套组件中切换类
【发布时间】:2014-04-12 09:11:57
【问题描述】:

我的根组件中有这样的 render() 方法:

render: function() {
    return (
        <div className="question">
            <QuestionA question={this.props.question} author={this.props.author}/>
            <QuestionB yes={this.state.yes} no={this.state.no} />
            <div className="question-side-switcher" onClick={this.handleSideChanging}></div>
        </div>
    );
}

当用户单击按钮时,我想在 QuestionA 和 QuestionB 组件之间切换“活动”类。我怎样才能做到这一点?请记住,QuestionA 和 QuestionB 在它们的 render() 方法中设置了它们自己的类名。比如 QuestionB 的 render():

render: function() {
    return (
        <section className="question-b-container">
            ...
        </section>
    );
}

【问题讨论】:

    标签: javascript class frameworks reactjs


    【解决方案1】:

    有几种方法可以解决这个问题。

    如果您希望父级控制附加类,您可以简单地将其传递给子组件,并让它们将其添加到现有的类名中 (JSFiddle demo):

    var QuestionA = React.createClass({
      render: function() {
        return <section className={this.props.className + " question-a-container"}>Section A</section>;
      }
    });
    
    var QuestionB = React.createClass({
      render: function() {
        return <section className={this.props.className + " question-b-container"}>Section B</section>;
      }
    });
    
    var Root = React.createClass({
      getInitialState: function() {
        return { question: 'a' };
      },
    
      render: function() {
        var qAclassName = this.state.question === 'a' ? 'active' : '';
        var qBclassName = this.state.question === 'b' ? 'active' : '';
        return (
          <div className="question">      
            <QuestionA className={qAclassName} />
            <QuestionB className={qBclassName} />
            <div className="question-side-switcher" onClick={this.handleSideChanging}>Change</div>
          </div>
        );
      },
    
      handleSideChanging: function() {
        this.setState({question: this.state.question === 'a' ? 'b' : 'a' });
      }
    });
    

    但是,让孩子管理类名可能更有意义,并简单地发送一些数据来指示它是否应该设置其活动类 (JSFiddle demo):

    // Using classSet to more easily create conditional class names;
    // see http://facebook.github.io/react/docs/class-name-manipulation.html
    var cx = React.addons.classSet;
    
    var QuestionA = React.createClass({
      render: function() {
        // always set "question-a-container";
        // set "active" if we got a truthy prop named `active`
        var className = cx({
          "question-a-container": true,
          "active": this.props.active
        });
        return <section className={className}>Section A</section>;
      }
    });
    
    var QuestionB = React.createClass({
      render: function() {
        // always set "question-b-container";
        // set "active" if we got a truthy prop named `active`
        var className = cx({
          "question-b-container": true,
          "active": this.props.active
        });
        return <section className={className}>Section B</section>;
      }
    });
    
    var Root = React.createClass({
      getInitialState: function() {
        return { question: 'a' };
      },
    
      render: function() {
        return (
          <div className="question">
            {/* For each question, compare to state to see if it's active. */}
            <QuestionA active={this.state.question === 'a'} />
            <QuestionB active={this.state.question === 'b'} />
            <div className="question-side-switcher" onClick={this.handleSideChanging}>Change</div>
          </div>
        );
      },
    
      handleSideChanging: function() {
        this.setState({question: this.state.question === 'a' ? 'b' : 'a' });
      }
    });
    

    【讨论】:

    • 我知道这一点,但认为 React 有另一个更清晰的解决方案。谢谢!
    • @Confa 我能想到的唯一另一件事是,如果您使用transferPropsTo 并且其中一个道具是className,它将与您正在使用的组件上设置的任何现有类合并打电话给transferPropsTo。见jsfiddle.net/BinaryMuse/XLDVS
    • 非常感谢!我已经看过classSet 的示例,但是您的解决方案看起来非常好。没听说过transferPropsTo。会看的。
    • 只是一个提醒类集已贬值。阅读说明。 facebook.github.io/react/docs/class-name-manipulation.html
    【解决方案2】:

    正如Brian Voelker 在comments 中提到的那样,现在在React 中操作类的官方方法是使用classnames 实用程序。

    你可以像这样定义你的两个组件:

    import React, { Component } from 'react'
    import classNames from 'classnames'
    
    class QuestionA extends Component {
    
      render () {
    
        const { active } = this.props
        const cx = classNames('question-a-container', { active })
    
        return (
          <section className={cx}></section>
        )
      }
    
    }
    

    然后只需向他们传递一个 active 属性来切换同名类。

    【讨论】:

      【解决方案3】:

      我遇到了与此类似的问题,我创建了一个选项卡式抽屉,我只渲染了 tabber 请求的组件,但这种解决方案并不理想,因为每次切换到另一个子组件时,我都会丢失子组件的状态制表师。

      为了避免在渲染中出现这种情况,我调用了一个函数来渲染我的所有孩子,在这个函数中,我将每个孩子包装在一个 div 中,并将所需的 className 分配给 div,在我的情况下,我需要为每个孩子显示一个组件时间,所以我使用 display:block 或 none 取决于单击的按钮。

      renderMyChilds() {
              var renderedComponents = this.props.children.map(function(child, _key) {
                  if(this.state.drawerOpened == true) {
                      var ElementToRender = child;
                      var MyElement = (this.state.buttonSelected != _key) ? <div className="hiddenComponent"><ElementToRender /></div> : <div><ElementToRender /></div>;
      
                  } else {
                      var ElementToRender = child;
                      var MyElement = <div><ElementToRender className="hiddenComponent" /></div>;
                  }
                  return (MyElement);
              }, this);
              return renderedComponents;
          }
      

      .hiddenComponent { 显示:无; }

      .visibleComponent { 显示:块; }

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2019-04-08
        • 1970-01-01
        • 1970-01-01
        • 2021-05-26
        • 2023-03-31
        • 1970-01-01
        • 2020-07-03
        相关资源
        最近更新 更多