Search code examples
ajaxreactjsfluxreactjs-flux

update reactjs context after ajax request finished with flux architecture


I need to update the context after an ajax request has finished. I'm using the flux architecture and everything works to the point that when my component is notified about the updated I need to set the new context.

A simple demostration:

I have a parent component which generates the context by calling a store. The store gets the data after an ajax request is initialized somewhere else. Like this:

RowAPI.ajaxGetAllRows();

Then I have my component which holds the context:

let ParentComponent = React.createClass({

    childContextTypes: {
        rows: React.PropTypes.object
    },

    getChildContext: function() {
        return {
            rows: RowStore.getAllRows(),
        };
    },

    componentDidMount: function() {
        RowStore.addChangeListener(this._onRowsChanged);
    },

    componentWillUnmount: function() {
        RowStore.removeChangeListener(this._onRowsChanged);
    },


    render() {

        return (
            <ChildComponent />
        );
    },

    _onRowsChanged: function() {
        //Now we need to update context
    }

});

Now since we are listening for row changes, we will get an update when our ajax request has finished and put the data into our store. Now we need to get that data and set it as context. That is the problem.

This is my child component that uses the context. I know that I just can pass the rows as a props to my child but this is just an example and in my real scenario I have many children which would need to pass the props.

let ChildComponent = React.createClass({

    contextTypes: {
        rows: React.PropTypes.object
    },


    render() {

        return (
            <div style={styles.wrapper}>
                {this.context.rows}
            </div>
        );

    },

});

Thanks in advance!


Solution

  • I would change the getChildContext in ParentComponent to refer to the state instead of a function call to the RowStore.

     getChildContext: function() {
            return {
                rows: this.state.rows,
            };
        }
    

    Then, whenever a row changes, and the _onRowsChanged callback it called, it can set this.state.rows accordingly.

    I believe that the issue with the original method of calling RowStore.getAllRows() inside getChildContext is that it is only called once. Nothing is forcing it to call RowStore.getAllRows() on every change.

    However, by using a state, you can use Flux concepts to "force" a change in state on every update, and that will be reflected in the context.