0

I'm in the process of translating a 90% complete website produced in HTML, CSS and jQuery into a more forward thinking react "application". I have some pretty basic principals that I'm struggling to get to grips with - I really like react's JSX language but and struggling to deal with heavy UI manipulation that I've achieve in jQuery previously.

To get me used to the concepts I'm starting with one of the most simple interactions on my website - Hover over the menu button and bring out the side menu partially (e.g. 20px). My components are structured like so:

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 includes the 'hamburger' button and the site title:

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

When "#menu-button" is hovered over I'm changing the state tree that I have defined in Baobab inside "teaseMenu()" using "menuActions.isHovering()".

....
teaseMenu: function(e) {
    menuActions.isHovering();
    // other stuff done
},....

What I'm struggling with is that once the change has been affected in my stateTree, I'm unsure how to then give the knowledge of this change to all of the other elements that rely on it. For example, how does the SideNav which is totally unrelated to "MainNav" and it's child "#menu-button" become aware of this change and alter it's state accordingly? This would simply be solved in jQuery with something like the following:

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

    },....

1 Answers1

0

Flux is a great way to do this, and I highly recommend you incorporate it in to your site as it'll make a lot of things easier. Have a read of this page for more information: https://facebook.github.io/flux/docs/overview.html

However you could also use state in your root App to affect change on MainNav whenever something occurs in SideNav.

Consider this change to your root app component:

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

The above is an example of how you can use the state of your root App to affect change on it's children. Your MainNav now takes a prop of onChange which is a function. This function is called by MainNav any time a change occurs that you want to notify your root App of. In this example case, the mainNavChangeHandler is executed with a boolean sideNavShowSomething variable. In your case you probably want to do something more complex ;)

So when you call this.props.onChange(true) in your MainNav then your root app will update it's state and SideNav will then receive this.props.showSomething as true wheras previously it was false. And by so doing you can affect change between child components by utilizing callbacks to the root App and handling new props to give children from them.

Mike Driver
  • 8,481
  • 3
  • 36
  • 37