使用 Baobab 影响多个组件的状态

State Affecting Multiple Components in React with Baobab

我正在将 HTML、CSS 和 jQuery 中制作的 90% 完整的网站翻译成更具前瞻性的 React "application"。我有一些非常基本的原则,我正在努力掌握这些原则——我真的很喜欢 React 的 JSX 语言,但也在努力处理我之前在 jQuery 中实现的繁重的 UI 操作。

为了让我习惯这些概念,我从我网站上最简单的交互之一开始——将鼠标悬停在菜单按钮上并部分显示侧边菜单(例如 20 像素)。我的组件结构如下:

var App = React.createClass({

    render: function() {
         return (
            <div id="reactWrap">
                <MainNav ref="main-nav"/>
                <SideNav projects={PROJECTS} ref="side-nav" />
                <RouteHandler projects={PROJECTS} ref="content" />
            </div>
        )
    }
});

MainNav 包括 'hamburger' 按钮和站点标题:

    render: function() {

        return (
            <nav className="fixed-nav">
              <div id="menu-button" onMouseEnter={this.teaseMenu} onMouseLeave={this.unteaseMenu} ref="menu-btn">   
                  <span className="menu-line"></span>
              </div>
              <span className="site-title">Lorem Ipsum</span>
            </nav>
        )
    } 

当“#menu-button”悬停时,我正在使用 "menuActions.isHovering()".

更改我在 "teaseMenu()" 内的 Baobab 中定义的状态树
....
teaseMenu: function(e) {
    menuActions.isHovering();
    // other stuff done
},....

我遇到的困难是,一旦更改在我的 stateTree 中受到影响,我就不确定如何将此更改的知识提供给依赖它的所有其他元素。例如,与 "MainNav" 完全无关并且它是 child "#menu-button" 的 SideNav 如何意识到这一变化并相应地改变它的状态?这可以简单地在 jQuery 中使用类似以下内容解决:

globalVars.menuBtn.on({
    mouseenter: function(e) {
        var self = $(this);
        var movePercentage = (-100 + (20 / globalVars.sideNavW * 100))/2;

        if (!pageStatus.menuActive) {
            globalVars.wrap.addClass('menu-hover');
            globalVars.sideNav.css({
                'left': movePercentage + '%'
            });
            menuBtnIn(e, self);
        }

    },....

Flux 是执行此操作的好方法,我强烈建议您将其合并到您的网站中,因为它会使很多事情变得更容易。阅读此页面以获取更多信息:https://facebook.github.io/flux/docs/overview.html

但是,只要 SideNav.

中发生某些事情,您也可以使用根 App 中的状态来影响 MainNav 上的变化

考虑对您的根应用程序组件进行此更改:

var App = React.createClass({
    getInitialState: function() {
        return {
            sideNavShowSomething: false
        }
    },

    mainNavChangeHandler: function(sideNavShowSomething) {
        this.setState({
            sideNavShowSomething: sideNavShowSomething
        })
    },

    render: function() {
         return (
            <div id="reactWrap">
                <MainNav ref="main-nav" onChange={this.mainNavChangeHandler} />
                <SideNav projects={PROJECTS} ref="side-nav" showSomething={this.state.sideNavShowSomething} />
                <RouteHandler projects={PROJECTS} ref="content" />
            </div>
        )
    }
});

以上示例说明了如何使用根 App 的状态来影响其子项的更改。你的 MainNav 现在接受 onChange 的一个函数,它是一个函数。每当发生您想要通知根 App 的更改时,MainNav 就会调用此函数。在此示例中,mainNavChangeHandler 是使用布尔值 sideNavShowSomething 变量执行的。在你的情况下,你可能想做一些更复杂的事情;)

因此,当您在 MainNav 中调用 this.props.onChange(true) 时,您的根应用程序将更新它的状态,然后 SideNav 将接收 this.props.showSomething 作为 true wheras 之前它是 false .通过这样做,您可以通过利用对根的回调 App 并处理新的道具来影响子组件之间的变化。