Skip to content

Calling a function in a component when a query parameter changes #579

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
tmcw opened this issue Dec 8, 2014 · 5 comments
Closed

Calling a function in a component when a query parameter changes #579

tmcw opened this issue Dec 8, 2014 · 5 comments

Comments

@tmcw
Copy link

tmcw commented Dec 8, 2014

Right now I'm working on moving some of our component state into query parameters so that pages are bookmarkable and other components can cleanly change the values.

It looks like react-router will call .render when a query parameter changes, but it's not clear how to tell which part of the URL / which query parameter changed, and the work I'm doing is outside of .render, in an onChange or componentDidUpdate lifecycle method.

Is there a clean way of implementing this? It seems like I either need to:

  • Duplicate the query parameters in the component's state so I know when they change
  • Or pass the query parameters down my view hierarchy from the router as a prop
@mhils
Copy link
Contributor

mhils commented Dec 12, 2014

I was wondering the same. Any hints? :-)

Cheers,
Max

@mhils
Copy link
Contributor

mhils commented Dec 12, 2014

Edit: You should use #579 (comment), not this.

FWIW, here's my current "workaround":

/*
Usage:
this.setQuery("search","42");
this.onQueryChange("search", console.log.bind(console));
*/
var Navigation = _.extend({
    setQuery: function (dict) {
        var q = this.context.getCurrentQuery();
        for(var i in dict){
            if(dict.hasOwnProperty(i)){
                q[i] = dict[i] || undefined; //falsey values shall be removed.
            }
        }
        this.replaceWith(this.context.getCurrentPath(), this.context.getCurrentParams(), q);
    },
}, ReactRouter.Navigation);
_.extend(Navigation.contextTypes, ReactRouter.State.contextTypes);

var State = _.extend({
    getInitialState: function () {
        this._query = this.context.getCurrentQuery();
        this._queryWatches = [];
    },
    onQueryChange: function (key, callback) {
        this._queryWatches.push({
            key: key,
            callback: callback
        });
    },
    componentWillReceiveProps: function (nextProps, nextState) {
        var q = this.context.getCurrentQuery();
        for (var i = 0; i < this._queryWatches.length; i++) {
            var watch = this._queryWatches[i];
            if (this._query[watch.key] !== q[watch.key]) {
                watch.callback(this._query[watch.key], q[watch.key], watch.key);
            }
        }
        this._query = q;
    }
}, ReactRouter.State);

@ryanflorence
Copy link
Member

If I need that info I pass the params/query down my route view hierarchy and let react's lifecycle hooks help me out.

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

// and then everywhere else:
<RouteHandler {...this.props}/>

Now its available here on every component:

  componentWillReceiveProps (nextProps) {
    var oldQuery = this.props.query;
    var newQuery = nextProps.query;
  }

edit thanks @abergs

@abergs
Copy link
Contributor

abergs commented Feb 5, 2015

@ryanflorence I believe you meant:

 componentWillReceiveProps (nextProps) {
    var old = this.props.query;
    var new = nextProps.query;
  }

@mhils
Copy link
Contributor

mhils commented Mar 27, 2015

FWIW, in 0.13.2 this.context.router.getCurrentQuery() always returns the same object reference (which is then updated). This makes passing it down the hierarchy as a prop to compare it with nextProps impossible (this.props is already updated as well). Cloning before passing it down the hierarchy is a possible workaround.

@remix-run remix-run deleted a comment from abelkbil Mar 28, 2018
@remix-run remix-run deleted a comment from techrah Mar 28, 2018
@remix-run remix-run locked and limited conversation to collaborators Mar 28, 2018
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

No branches or pull requests

4 participants