React-router: BrowserRouter v4 not providing context to children

Created on 22 Nov 2016  路  1Comment  路  Source: ReactTraining/react-router

Version

v4.0.0-alpha.6

Context

I'm having issues with programmatically redirecting the user to a page after a resource is created e.g:

const App = (props) => {
    const handleClick = (event) => {
        return fetch(/* someurl */, { method: 'POST' /* ... */ })
            .then(res => res.json())
            .then(res => {
                // redirect to `/resource/${ res.data.resource.id }`
            });
    };

    return (<p>Hello world! <button onClick={ handleClick }>+ Create resource</button></p>);
};

It seems that I should be calling the transitionTo method on the router context, however I don't seem to have access to the router property.

Steps to reproduce

const AppContainer = () => {
    <BrowserRouter>
        <App testing={ true } /> {/* see App definition above */}
    </BrowserRouter>
};

ReactDOM.render(<AppContainer store={ store } client={ client }/>, document.querySelector('#app'));

Expected Behavior

I'd expect that inside App the props should contain:

{
    testing: true,
    router, // router context
    action,
    location
}

Actual Behavior

The props passed to App contains testing only.

It seems to me that the issue lies in the StaticRouter, where we check for the type of the children property in order to render it correctly.

children is something that looks like:

{
    "key": null,
    "_store": {},
    "props": {
        "testing": true
    },
    "ref": null,
    "type": function App(props) 
}

It is clear to me that typeof children will never be function. Should the code be looking at children.type instead?

I know very little about the inner workings of ReactRouter but it also appears at first glance that if the condition was right we'd lose the original properties (in this case testing)?

Any help would be much appreciated.

Most helpful comment

Seems that I missed the fact that ReactRouter uses Context as @Xan rightly pointed out on the Discord #react-router channel.

By adding:

App.contextTypes = {
    router: React.PropTypes.object
};

I could access the router context like:

const App = (props, context) => {
    const handleClick = (event) => {
        return fetch(/* someurl */, { method: 'POST' /* ... */ })
            .then(res => res.json())
            .then(res => {
                context.router.transitionTo(/* ... */);
            });
    };

    return (<p>Hello world! <button onClick={ handleClick }>+ Create resource</button></p>);
};

>All comments

Seems that I missed the fact that ReactRouter uses Context as @Xan rightly pointed out on the Discord #react-router channel.

By adding:

App.contextTypes = {
    router: React.PropTypes.object
};

I could access the router context like:

const App = (props, context) => {
    const handleClick = (event) => {
        return fetch(/* someurl */, { method: 'POST' /* ... */ })
            .then(res => res.json())
            .then(res => {
                context.router.transitionTo(/* ... */);
            });
    };

    return (<p>Hello world! <button onClick={ handleClick }>+ Create resource</button></p>);
};
Was this page helpful?
0 / 5 - 0 ratings

Related issues

Radivarig picture Radivarig  路  3Comments

jzimmek picture jzimmek  路  3Comments

imWildCat picture imWildCat  路  3Comments

andrewpillar picture andrewpillar  路  3Comments

Waquo picture Waquo  路  3Comments