RickWong/react-transmit

How to set queryParams from react-router params

minhtranite opened this issue · 7 comments

...
var PageHome = require('components/PageHome');
var PageMeasurements = require('react-proxy?name=page-measurements!components/PageMeasurements');
var PageMeasurementsTab = require('react-proxy?name=page-measurements-tab!components/PageMeasurementsTab');
var PageMeasurementsAdd = require('react-proxy?name=page-measurements-add!components/PageMeasurementsAdd');
var PageNotFound = require('react-proxy?name=page-not-found!components/PageNotFound');
var routes = (
  <Route name="app" path="/" handler={App}>
    <DefaultRoute name="page-home" handler={PageHome}/>
    <Route name="page-measurements" path="measurements" handler={PageMeasurements}>
      <Route name="page-measurements-tab" path=":category/:type" handler={PageMeasurementsTab}>
        <Route name="page-measurements-add" path="add" handler={PageMeasurementsAdd}/>
      </Route>
    </Route>
    <NotFoundRoute name="not-found" handler={PageNotFound}/>
  </Route>
);

Router.run(routes, Router.HistoryLocation, function (Handler, state) {
  React.render(<Handler data="xxx" queryParams={state.params}/>, document.body);
});

With 'PageMeasurementsTab' (Transmit component) I can't get data, queryParams prod.
screenshot from 2015-04-10 15 17 52

With 'PageHome' (normal React component) I can get data, queryParams prod
screenshot from 2015-04-10 15 18 12

In my case, with url 'measurements/:category/:type' i want 'Transmit' get data from '/api/measurements?category=:category&type=:type' instead of '/api/measurements'.

I try change queryParams in 'componentWillMount' :

componentWillMount: function() {
        this.props.setQueryParams({
            category: this.context.router.getCurrentParams().category,
            type: this.context.router.getCurrentParams().type
        });
    },

but 'Transmit' will get data two time.
screenshot from 2015-04-10 15 26 38

How does the resolved Handler component look like? I'd definitely use this.context.router too but I'll need to see the Handler component to tell you how more specifically.

PageMeasurementsTab.js:

var React = require('react');
var {Link, RouteHandler} = require('react-router');
var Transmit = require('react-transmit');
var MeasurementsService = require('services/MeasurementsService');
var _ =require('underscore');
var ImageViewer = require('components/ImageViewer');

var PageMeasurementsTab = React.createClass({
    contextTypes: {
    router: React.PropTypes.func
  },
    componentWillMount: function() {
        this.props.setQueryParams({
            category: this.context.router.getCurrentParams().category,
            type: this.context.router.getCurrentParams().type
        });
    },
    renderMeasurements: function(){
        return _.map(this.props.measurements, function(measurement){
            return (
                <tr key={measurement.id}>
                    <td><ImageViewer data-src={measurement.image} width="100" height="80"/></td>
                    <td>{measurement.title}</td>
                    <td>{measurement.instruction}</td>
                    <td>{measurement.video}</td>
                    <td>{measurement.created_at}</td>
                    <td>{measurement.id}</td>
                    <td></td>
                </tr>
            );
        });
    },
    render: function() {
        var category = this.context.router.getCurrentParams().category;
        var type = this.context.router.getCurrentParams().type;
        return (
            <div>
                <section className="action-bar">
                    <Link className="btn btn-primary" to="page-measurements-add" params={{category: category, type: type}}>
                        <i className="glyphicon glyphicon-plus"></i> Add new measurement
                    </Link>
                    <form className="action-bar-search-form form-inline pull-right">
                      <div className="form-group">
                        <div className="input-group">
                          <input type="text" className="form-control" 
                            placeholder="Search measurement"></input>
                          <span className="input-group-btn">
                            <button className="btn btn-default" type="button">
                                <i className="glyphicon glyphicon-search"></i>
                            </button>
                          </span>
                        </div>
                      </div>
                    </form>
                </section>
                <table className="table table-bordered">
                    <thead>
                        <tr>
                            <th></th>
                            <th>Title</th>
                            <th>Instruction</th>
                            <th>Video</th>
                            <th>Created</th>
                            <th>ID</th>
                            <th>Options</th>
                        </tr>
                        <tbody>
                            {this.renderMeasurements()}
                        </tbody>
                    </thead>
                </table>
                <RouteHandler/>
            </div>
        );
    }

});

module.exports = Transmit.createContainer(PageMeasurementsTab, {
    queries: {
        measurements: function(queryParams){
            return MeasurementsService.query(queryParams).then(function(response){
                return response.body;
            });
        }
    }
});

MeasurementsService.js:

var Config = require('config');
var Request = require('superagent');
var prefix = require('superagent-prefix')(Config.apiPrefix);
var Promise = require('promise');

var MeasurementsService = {
    query: function(params){
        var queries = params || {};
        return new Promise(function(resolve, reject){
            Request.get('/api/measurements')
                .use(prefix)
                .query(queries)
                .end(function(error, response){
            if(error){
                reject(error);
            }
            resolve(response);
        });
        });
    }
};

module.exports = MeasurementsService;

Hmmmm.... In the first solution, the one that doesn't use context:

Transmit.createContainer(PageMeasurementsTab, {
    queries: {
        measurements: function(queryParams){

           /**!!!! .... queryParams should contain the {state.params} here !!!**/

            return MeasurementsService.query(queryParams).then(function(response){
                return response.body;
            });
        }
    }
});

@vn38minhtran Did you have the time to verify the above? I'll leave this issue open for a bit longer.

Thanks for help! I will close issue and try your solution laster.

@RickWong actually your solution doesn't work for me.

Transmit.createContainer(PageMeasurementsTab, {
    queries: {
        measurements: function(queryParams){

           /**!!!! .... queryParams should contain the {state.params} here !!!**/

            return MeasurementsService.query(queryParams).then(function(response){
                return response.body;
            });
        }
    }
});

queryParams doesnt' contain state.params. Container resets passed props. Isn't this a typo?

componentWillMount: function() {
      var externalQueryParams = this.props && this.props.queryParams || {}; // shoudn't it be || instead of && ? 
      this.currentParams = assign({}, Container.queryParams, externalQueryParams);
      if (!this.hasQueryResults()) {
        this.setQueryParams({});
      } else if (this.props.onQuery) {
        this.props.onQuery.call(this, Promise.resolve({}));
      }
    },

My bad, was a bug in my code.