How to deal with query params in react + react-router + flux
Asked Answered
O

2

24

I'm trying to replace a Backbone.Marionette App to React and am facing difficulty thinking about query params. I think I'm missing a really simple peace in understanding this pattern so I apologize if this question is totally nonsense. I would appreciate any support or just pointing me to some direction that I can google more specifically.

There's a /users page which lists users and you can filter the users via search bar. So if you want to filter the users which contain 'joe' in their username, I would make a request to the server with query params like /users?username=joe. In addition I am able to paginate by adding a page parameter, too (/users?username=joe&page=1).

If I only think about the functionality, the flow would probably be

  1. The Client inserts joe to the input element and clicks Search.
  2. Clicking the Search button fires an Action (like Action.getUser).
  3. The Action makes a request to the server and receives the results
  4. The Dispatcher dispatches a function with the results payload to whomever (usually the Store) is interested in the Action.
  5. The Store's state changes with the new result received by the Action
  6. The View (Component) re-renders by listening to the Store's change.

and it works as expected. However, I would like the Client to be able to bookmark the current filtered result and be able to come back to the same page some time later. This means I will need somewhere to save explicit information about the search term the Client made, which is usually the url (am I right?). So I will need to update the url with query parameters to save the search term (/users?username=joe&page=1).

What I'm confused is where and when to update the url? What I can come up with right now are the 2 options below - and they don't seem to be clean at all.

Option 1

  1. The Client inserts joe to the input element and clicks Search.
  2. Clicking the Search button fires a transition of the ReactRouter with the new query params (/users?username=joe&page=1).
  3. The View (Component) receives the new params via this.props.params and this.props.query.
  4. The View (Component) fires an Action like Action.getUser depending on the query params it receives - in this case username=joe&page=1.

after this, it is the same as above

Option 2 (only 6 is different from what I explained above)

  1. The Client inserts joe to the input element and clicks Search.
  2. Clicking the Search button fires an Action (like Action.getUser).
  3. The Action makes a request to the server and receives the results
  4. The Dispatcher dispatches a function with the results payload to whomever (usually the Store) is interested in the Action.
  5. The Store's state changes with the new result received by the Action
  6. The View (Component) re-renders by listening to the Store's change. And somehow (I don't know how, yet) updates its url depending on its props (like this.props.searchusername, and this.props.searchpage)

What is the best practice on handling query params? (or this may not be specific to query params) Am I completely misunderstanding the design pattern or architecture? Thanks in advance for any support.

Some articles I've read

Organelle answered 25/8, 2015 at 15:56 Comment(0)
T
1

Not entirely sure what you mean by

this means I will need to update the url to save the information (/users?username=joe&page=1).

You will probably have a similar structure to this.

TopContainer.jsx -- Users.jsx -- a list of User.jsx

Usually TopContainer will watch all the stores and if anything changed, pass it down to users.jsx. That way in Users.jsx, you can simply render this.props.users without worrying about any reRendering.

The search users actions usually happens in TopContainer's componentWillMount event, and you the page will listen to UserStore. That's a good place to throw in any query params. Something like this would work

  componentWillUnmount() {
    let searchTerm = router.getCurrentQuery().searchTerm;
    UserActions.searchUsers(searchTerm)
  },

The page doesn't really care if the url has a query params or not, it just dumbly shows whatever in the user store.

Then when the search finishes, Users.jsx will be reloaded and show the correct results

Tramroad answered 25/8, 2015 at 16:26 Comment(4)
Thanks for the suggestion. In order for somebody to bookmark the search result, I thought you would need some explicit information about the search term. Which would be the url. Am I right about this?? I still am not clear how the URL gets updated when the user clicks the Search button. Is option 1 closer to your solution?? Sorry about my not having enough knowledge. I really appreciate your help.Organelle
I see what you mean. I think you are looking for github.com/rackt/react-router/blob/…Tramroad
Basically navigate to the same page with params(this case your search terms)Tramroad
The op means to ask, where in the above cycle of TopContainer.jsx -- Users.jsx -- a list of User.jsx would you put query params in the URL, as in what component is responsible to do that?Dunedin
L
2

I would consider best practice to be the submit button only setting the location query (username). The rest should be taken care by the main react component that is assigned as router component. By this, you can be sure that anytime one revisits or shares the url, they can get the same results. And this is very generic too.

Something like this:

let myQuery = this.props.location.query;
if (myQuery.username) {
  let theUser = myQuery.username;
  this.setState({
    userName = myQuery.username
  });
} else {
  this.setState({
    userName = false //Show All
  });
} 

And then use this state "userName" to send to the server to search with. By this way, you will not need to iterate the code of the component that takes care of listing users since server already sends the relevant data.

In my experience with using location queries in React, I have been very content with their reactivity cycles and performance. I'd highly recommend keeping every different app state in relevance with the url.

Latterday answered 7/12, 2015 at 15:10 Comment(0)
T
1

Not entirely sure what you mean by

this means I will need to update the url to save the information (/users?username=joe&page=1).

You will probably have a similar structure to this.

TopContainer.jsx -- Users.jsx -- a list of User.jsx

Usually TopContainer will watch all the stores and if anything changed, pass it down to users.jsx. That way in Users.jsx, you can simply render this.props.users without worrying about any reRendering.

The search users actions usually happens in TopContainer's componentWillMount event, and you the page will listen to UserStore. That's a good place to throw in any query params. Something like this would work

  componentWillUnmount() {
    let searchTerm = router.getCurrentQuery().searchTerm;
    UserActions.searchUsers(searchTerm)
  },

The page doesn't really care if the url has a query params or not, it just dumbly shows whatever in the user store.

Then when the search finishes, Users.jsx will be reloaded and show the correct results

Tramroad answered 25/8, 2015 at 16:26 Comment(4)
Thanks for the suggestion. In order for somebody to bookmark the search result, I thought you would need some explicit information about the search term. Which would be the url. Am I right about this?? I still am not clear how the URL gets updated when the user clicks the Search button. Is option 1 closer to your solution?? Sorry about my not having enough knowledge. I really appreciate your help.Organelle
I see what you mean. I think you are looking for github.com/rackt/react-router/blob/…Tramroad
Basically navigate to the same page with params(this case your search terms)Tramroad
The op means to ask, where in the above cycle of TopContainer.jsx -- Users.jsx -- a list of User.jsx would you put query params in the URL, as in what component is responsible to do that?Dunedin

© 2022 - 2024 — McMap. All rights reserved.