Yomguithereal/baobab-react

Baobab seemingly not passing context to children

williamrenwick opened this issue · 8 comments

I'm fairly new to react and am wanting to implement react-router and baobab-react into my small scale application, along with using webpack to bundle my code up.

My main.js entry file looks like this:

var React = require('react');
var Router = require("react-router");
var routes = require("./routing/routes");
var stateTree = require('./data/stateTree.js')

Router.run(routes, (Root, state) => {
  React.render(<Root tree={stateTree} {...state} />, document.body);
});

The main "App" component is rendered in a separate file and has the root mixin passed to it (note the console I'm doing as this is how I'm detecting the error):

var rootMixin = require('baobab-react/mixins').root;
// ....other relevant variables

var App = React.createClass({
    mixins: [rootMixin],
    render: function() {
        console.log("app", this.state, this.props, this.getChildContext());
        return (
            <div id="reactWrap">
                <MainNav ref="main-nav"/>
                <SideNav projects={PROJECTS} ref="side-nav" />
                <RouteHandler projects={PROJECTS} ref="content" />
            </div>
        )
    }
});

SideNav is one of the components that I want to use a branch of the state tree with and it's defined like so (again I'm consoling to see what is passed to the child component):

var mixin = require('baobab-react/mixins').branch
// ....other relevant variables

var SideNav = React.createClass({
    mixin: [mixin],
    cursors: {
        menu: ['menu', 'bumpAmount']
    },  
    render: function() {
        console.log("sidenav", this.props, this.state, this.context);
        return (
            <nav id="side-nav">
                <MainSide />
                <ProjectSide projects={this.props.projects}/>
            </nav>
        )
    }
});

Here's what I'm seeing in the console when the page initialises:

app, null, Object {tree: Baobab, path: "/", action: null, pathname: "/", routes: Array[2]}, Object {tree: Baobab}

sidenav, Object {projects: Array[3]}, null, Object {}

As you can see the context of the child component is consoling as an empty object and state in both cases is null. For clarity here are is my stateTree and my action file

var Baobab = require('baobab');

var stateTree = new Baobab({
    menu: {
        isHovering: false,
        bumpAmount: 0,
        isOpen: false
    }
})

I have an on.('change',...) listener on these values and their state is being updated fine - the issue seems to be in the actual passing of the context. Perhaps I'm doing something very obviously wrong but myself and another dev who's very familiar with React and some other flux architecture can't spot this issue. Any pointers would be enormously helpful.

If you wish to view the code in more detail here's the link to the Git: https://github.com/williamrenwick/build-v3.0

Hello @williamrenwick. It's possible #52 and #61 refers to the same issue as yours. You are using react-router aren't you? There might be an issue with them rendering this.props.children and getting it out of context.

Let me check this more thoroughly.

@Yomguithereal Yes I'm using react-router and webpack as part of my stack. However I did test it without react-router (I removed the Router.run wrapping function and just used React.render(<App tree={stateTree} />, document.body); and the <RouteHandler projects={PROJECTS} ref="content" /> and I still had the same issue.

Ok, I'll check that more carefully.

Hi @Yomguithereal and @williamrenwick I'm using react router without problems, I only notice a small diference in the parameters of Router.run, can you check this small code?

var data = {tree :  new Baobab...}

var Hello = React.createClass({
    mixins: [mixins.branch],
    cursors: {msg: ['message']}, //change according to your tree
    render() {
        return (
            <div>hello {this.state.msg}</div>
        )
    }
});

var Container = React.createClass({
    mixins: [mixins.root],
    render() {

        return (
            <div>                 
                    <RouteHandler/>        
            </div>
        )
    }
});



var routes = (
    <Route handler={Container}>
        <Route path="/hi" handler={Hello}></Route>
    </Route>
)


Router.run(routes, Router.HashLocation, (Root)=> {
    React.render(<Root tree={data.tree}/>, document.getElementById('main'))
}); 

@cocodrino @Yomguithereal I've tried passing in the following to the 'run' method of 'Router' inside my main.js app root and it still consoled the same results as in my original post. Thanks for the idea though!

var React = require('react');
var Router = require("react-router");
var routes = require("./routing/routes");
var stateTree = require('./data/stateTree.js')

Router.run(routes, Router.HashLocation, (Root) => {
  React.render(<Root tree={stateTree} />, document.body);
});

As mentioned I think could possible be to do with webpack. If the above is working in a single file then it would make sense that perhaps my modules aren't allowing the context to be passed to the children. Particularly since the log of getChildContext() inside of the 'App' component returns the tree, but the children of that component return an empty object when their context is logged yet removing react-router has no effect.

hi @williamrenwick I've notice than you're using the word 'mixin' instead of 'mixins'

var SideNav = React.createClass({
    mixin: [mixin]

maybe that is the problem .

@cocodrino You are absolutely right! God, what a waste of everyones time, so sorry. Debugging in a rush always leads to overlooking the most basic of explanations for errors. Thank you!

Nice one @cocodrino. Thanks for spotting this!