ReactJs - 为什么 child 事件不会更改 parent 的状态?

ReactJs - Why wont child event change state of parent?

我在 reactjs 中创建了一个菜单组件。如您所见,parent 组件有一个名为 "handleClick which toggles the "open state" 的菜单方法,可以相应地打开和关闭菜单。

现在,我试图将点击事件从 child 组件 "MenuItem"(它是菜单中的 link)传递到 parent "Menu" 组件,以便在单击菜单项之一时关闭菜单。

我尝试过多种方式来做到这一点。目前,我已经将 "MenuList"(MenuItems 列表)中每个 "MenuItem" 的点击事件绑定到一个名为 "whenClicked" 的道具,然后将 "whenClicked" 绑定到 [= "Menu".

的 30=] 方法

问题是这似乎对 "Menu" 没有影响。 Chrome 中的 React 工具和常规开发控制台都没有给我任何错误,但是当我单击其中一个 MenuItems 时菜单没有关闭。 Chrome 中的 React 工具允许我查看虚拟 DOM,我可以看到所有的 onClick 函数都已定义。

下面是代码。如您所见,我使用相同的方法将点击事件从不同的组件 ("MenuToggle") 传递到 "Menu"。奇怪的是,这工作正常,单击切换按钮成功更改 "Menu" 的状态并打开和关闭菜单。我正在为 "MenuItem" 使用 "react-scroll" 模块,所以这可能就是问题所在。任何人都可以对此有所帮助,我很想知道我做错了什么!

var Menu = React.createClass({

    getInitialState: function() {
        return {open: false, mobi: false}
    },
    handleClick: function() {
        this.setState({open: !this.state.open})
    },
    closeOnMobiScroll: function() {
        /*
        if(this.state.mobi === false) {
            this.setState({open: false})
        }
        */
    },
    updateDimensions: function() {
        $(window).width() >= 767 ? this.setState({mobi: true}) : this.setState({mobi: false});
    },
    componentWillMount: function() {
        this.updateDimensions();
    },
    componentDidMount: function() {
        $(window).on("resize", this.updateDimensions);
    },
    componentWillUnmount: function() {
        $(window).on("resize", this.updateDimensions);
    },
    render: function() {
        return (

            <div id="menu" className={(this.state.open ? 'open' : '')} >
                <div id="menu-inner-wrap">
                    <MenuTitle />
                    <MenuToggle whenClicked={this.handleClick}/>
                    <MenuList whenClicked={this.handleClick}/>
                </div>
            </div>

        )
    }

});

module.exports = Menu;

var MenuItem = React.createClass({

    render: function() {
        return (
            <li className="menu-link">
                <Link to={this.props.menuLink} spy={true} smooth={true} duration={500}>
                    <i className={this.props.icon}></i>
                    <span className="menu-link-text">{this.props.menuTitle}</span>
                </Link>
            </li>
        );
    }
});

var MenuList = React.createClass({
    getInitialState: function() {
        return {data: []}
    },
    componentWillMount: function() {
        $.ajax({
            url: 'http://10.0.0.97:8888/public-code/React.cv/data/data.json',
            dataType: 'json',
            success: function(data) {
                this.setState({data: data});
            }.bind(this),
            error: function(xhr, status, error) {
                var err = JSON.parse(xhr.responseText);
                console.log(err.Message);
            }
        });
    },
    render: function() {
        var list = this.state.data.map(function(menuItemProps) {
            return <MenuItem onClick={this.props.whenClicked} {...menuItemProps} key={menuItemProps.id} />
        }.bind(this));
        return (
            <ul id="menu-list">
                {list}
            </ul>
        )
    }
});

看来您仍然需要将 onClick 绑定到 DOM 将处理的内容。在MenuItem上加一个onClick属性,可以让MenuItem里面有一个prop,但是还是需要绑定:

var MenuItem = React.createClass({

    render: function() {
        return (
            <li className="menu-link" onClick={this.props.onClick}>
                <Link to={this.props.menuLink} spy={true} smooth={true} duration={500}>
                    <i className={this.props.icon}></i>
                    <span className="menu-link-text">{this.props.menuTitle}</span>
                </Link>
            </li>
        );
    }
});

}

在上面的例子中,onClick被添加到li:

<li className="menu-link" onClick={this.props.onClick}>

此类行为文档中的最佳示例在 Expose Component Functions

在该示例中,您可以看到 Todo 子组件最终绑定到 div,然后以类似的方式冒泡:

var Todo = React.createClass({
  render: function() {
    return <div onClick={this.props.onClick}>{this.props.title}</div>;
  },

  //this component will be accessed by the parent through the `ref` attribute
  animate: function() {
    console.log('Pretend %s is animating', this.props.title);
  }
});