ReactJS - 在组件之间传递状态的变化

时间:2015-06-10 22:44:59

标签: reactjs

我有以下组件:

enter image description here

由于我的按钮组件是通用的,它的事件也是通用的,我的无序列表也是如此;它是设置事件的下拉列表。以下是两者的相关代码:

按钮组件:

render(){
  return(

    {/* whenClicked is a dropdown property  /*}
    <button onClick={this.props.whenClicked} type="button">
    .....
    </button>
    )

无序列表组件:

constructor(props) {
    super(props);
    this.state = {
        open:false
    }
}
render(){
    return(

         {/* toggle between show and hide  /*}
        <ul className={"dropdown-menu " + (this.state.open ? 'show' : '')}>
            {this.props.dropItems.map(function(item){
               ......
            })}
        </ul>
    )
}

由于按钮组件是通用的,其点击事件取决于下拉组件 whenClicked 属性。

下拉组件:

   'use strict'; 
   var React = require('react'),
       Button = require('./button'),
       UnorderedList = require('./unordered-list');

   class Dropdown extends React.Component{

   constructor(props) {
      super(props);
      this.state = {
          open:false
      }

     // added this as an update to my question per ssorallen
        this.handleClick = this.handleClick.bind(this)
   }

   handleClick(){
      this.setState({open : !this.state.open});
   }

  render(){

      return(
          <div className="dropdown">
              {/* whenClicked is a property not an event, per se. */}
              <Button whenClicked={this.handleClick}  />
              ......
             {/* // prop.items comes from app.jsx  */}
              <UnorderedList dropItems={this.props.items} />
          </div>
      )
  } }

   module.exports = Dropdown;

App.jsx:

 ....
       var selectItems = {
           title : "Choose a Fruit",
           items : [
               "Cantaloupe",
                .........
        ]
    }

    <Dropdown items={selectItems.items} multiSelect={true} title={selectItems.title} />
....

此图片中发生了什么:

  1. App.jsx将水果项目传递给下拉组件

  2. 下拉列表依次将这些项目传递到无序列表

  3. 按钮组件连接到clicked属性时的下拉列表。

  4. unorderlist组件的初始状态打开设置为 false ,符合其属性:

      className={"dropdown-menu " + (this.state.open ? 'show' : '')}
    
  5. 这一切都有效。

    我的问题:

    单击该按钮时,系统会触发下拉单击事件时触发并切换打开状态

    该事件假设触发无序列表以在真实和&amp;之间切换它的打开状态。 false,从而在其类&#34;下拉菜单&#34;中添加/删除显示

    当state.open发生变化时,有人可以告诉我如何让下拉组件与无序列表进行通信吗?

    我得到的错误是:

    未捕获的TypeError:无法读取属性&#39; setState&#39;未定义的

2 个答案:

答案 0 :(得分:3)

使用ES6类扩展React.Component时,成员方法不再像将对象传递给React.createClass时那样“自动绑定”。您可以bind them in the constructor获取您习惯的行为:

class Dropdown extends React.Component {

  constructor() {
    ...
    this.handleClick = this.handleClick.bind(this);
  }

  render() {
    ...
    <div onClick={this.handleClick}>
    </div>
    ...
  }

}

答案 1 :(得分:1)

<强>解决方案:

  1. 完全从UnorderedList类中删除状态。
  2. 在Dropdown中创建toggleState prop w /状态值为UnorderedList,
  3. 将该属性传递给UnorderedList的'dropdown-menu'类。
  4. UnorderedList class:

     'use strict';
     var React = require('react');
    
     class UnorderedList extends React.Component{
    
         constructor(props) {
             super(props);
         }
         render(){
             var listItemStyle = {
                 cursor:'pointer'
             };
    
        return(
            <ul className={"dropdown-menu " + (this.props.toggleState ? 'show' : '')} role='menu' aria-labelledby='dropdownMenu1'>
                {this.props.dropItems.map(function(item){
                    return (<li style={listItemStyle} key={item}><a>{item}</a></li>)
                })}
            </ul>
        )
    } }
    
      module.exports = UnorderedList;
    

    下拉课程:

      'use strict';
      var React = require('react'),
          Button = require('./button'),
          UnorderedList = require('./unordered-list');
    
      class Dropdown extends React.Component{
    
          constructor(props) {
              super(props);
              this.state = {
                  open:false
              }
              this.handleClick = this.handleClick.bind(this)
          }
    
    handleClick(){
        this.setState({open : !this.state.open});
    }
    
    render(){
        return(
            <div className="dropdown">
                {/* whenClicked is a property not an event, per se. */}
                <Button whenClicked={this.handleClick} className="btn-warning" title={this.props.title} subTitleClassName="caret"></Button>
                <UnorderedList dropItems={this.props.items} toggleState={this.state.open} />
            </div>
        )
      }
     }
       module.exports = Dropdown;