https://github.com/yiransheng/react-query-param
react-query-param
https://github.com/yiransheng/react-query-param
query-params react redux router side-effects
Last synced: 11 months ago
JSON representation
react-query-param
- Host: GitHub
- URL: https://github.com/yiransheng/react-query-param
- Owner: yiransheng
- Created: 2017-03-13T01:48:54.000Z (almost 9 years ago)
- Default Branch: master
- Last Pushed: 2017-05-16T23:58:00.000Z (almost 9 years ago)
- Last Synced: 2025-04-14T12:06:15.709Z (11 months ago)
- Topics: query-params, react, redux, router, side-effects
- Language: JavaScript
- Size: 951 KB
- Stars: 3
- Watchers: 2
- Forks: 1
- Open Issues: 0
-
Metadata Files:
- Readme: README.md
Awesome Lists containing this project
README
# `react-query-param`
A `react-router@v4` inspired url query parameter library.
## Demo
[Simple Example With History](http://react-query-param-history.surge.sh)
[Example with Router](http://able-vase.surge.sh)
## Example
See: `examples/WithHistory` for a from-scratch integration with `redux` and `history`.
See: `examples/WithReactRouter` for integration with `react-router` and `react-router-redux`
## Overview
This library exports two components:
* `UrlQuery`
* `QueryParam`
You should include `UrlQuery` somewhere high up in the component tree, like `Provider` from `react-redux`. For example:
```javascript
ReactDOM.render((
), document.getElementById('root'));
```
Of course, this is not a requirement, you can use `UrlQuery` for the part of component tree where query parameter actually matters.
`QueryParam` takes two props: `name` and `values`, and renders nothing but its children - and passes its props up to `UrlQuery` through the use of `React` context. `values` can be either a string of array of parameter values. For exampe:
```javascript
console.log(query)}>
```
The above code by itself does not actually modify page url. It only logs changes whenever the component mounts or updates. Mounting the above for the first time will log:
```
{
q : "search term",
page : "1"
}
```
`QueryParam` can be nested:
```
```
This will fire `onChange` at root `UrlQuery` with the following:
```
{
topKey : ["by", "children"]
}
```
## Recommended Use Case
This library is designed to work with `redux`, it is recommended to `connect` your components, and pass data for query parameter to `QueryParam` from any parts of your store. Unlike integrating `react-router` with `redux` (through `react-router-redux`), no restriction is placed on how you organize your store. `react-router-redux` forces a root store `router` and `url ` is stored on `location.pathname` as a string. `react-url-param` encourages you to use any data type suitable for the you app, and maps your data to query parameters inside `React` components.
Consider the following store layout:
```javascript
// store shape:
const state = {
currentSearch : {
query : "",
limit : 50
},
currentProject : "slug-1",
entities : {
projects : {
"slug-1" : {
createdAt,
name,
permissions
},
"slug-2" : {
createdAt,
name,
permissions
}
},
items : {
"1" : {
id : 1,
project : "slug-1",
data
},
"2" : {
id : 2,
project : "slug-2",
data
}
}
}
}
```
In your components, declaratively specify query parameters.
```
@connect((state) => {
return {
project : state.currentProject,
searchQuery : state.currentSearch.query,
searchLimit : state.currentSearch.limit,
items : filterByProjectAndSearch(
state.currentProject,
state.currentSearch.query,
state.currentSearch.limit,
state.entities.items
)
};
})
class App extends Component {
render() {
const {searchQuery, project, items} = this.props;
return (
);
}
}
```
`` will trigger side effects, unlike normal react components. However, it's is up to you to implement `onChange` at `` root level, so side effects are centralized and maintained in on place. One example for `onChange`:
```javascript
import {stringify} from 'query-string';
const handleQueryChange = (query) => {
// the query payload is compatible with `query-string` libaray
window.location.search = stringify(query);
}
// -- some component
render() {
{/* app components */}
}
```
With this change, any time you data in redux store changes, url is automatically updated to reflect it - making url bar just another render target of `React`. However, this only takes care of one way data sync, if the user updates the url via back button (or upon initial page load), we do not have a mechanism to notify `redux` `store` about the changes. Unfortunately this part is very app specific, and a managed solution can be difficult to achieve. To do this mannualy (using `history` library):
```javascript
import createBrowserHistory from 'history/createBrowserHistory';
import {parse} from 'query-string';
const history = createBrowserHistory();
const locationToActions = location => {
const query = parse(location.search);
const actions = [];
if (query.project) {
actions.push({
type : UPDATE_CURRENT_PROJECT,
payload : query.project
});
}
if (query.q) {
actions.push({
type : UPDATE_CURRENT_SEARCH,
payload : query.q
})
}
// ... this function can be composed by a lot of smaller funcitons
return actions;
}
const unlisten = history.listen(location => {
locationToActions(location).forEach(store.dispatch);
});
const initialState =
locationToActions(history.location).reduce(rootReducer, preloadedState);
const store = createStore(rootReducer, initialState);
// later inside React
history.push({...location, query, search:stringify(query)}) }
/>
```