Giter VIP home page Giter VIP logo

use-route-as-state's Introduction

use-route-as-state

Use React Router route and query string as component state

Warning

Deprecation Warning: This package does not support react-router v6 (see issue #172).

npm npm Release Github Pages

Install

npm install --save use-route-as-state

Usage

You can see a live demo, including code, here.

// URL: /:param?query=
import * as React from "react";

import { useRouteParams, useQueryString } from "use-route-as-state";

const Example = () => {
  const [{ param }, setRouteParams] = useRouteParams();
  const [{ query }, setQueryParams] = useQueryString();

  return (
    <div>
      <input
        value={param}
        onChange={({ target }) => setRouteParams({ param: target.value })}
      />
      <input
        value={query}
        onChange={({ target }) => setQueryString({ query: target.value })}
      />
    </div>
  );
};

API

This library is trying to behave like the useState React hook, by exposing a similar interface.

type DispatchState<TState> = Dispatch<SetStateAction<TState>>;
type RouteObject = Record<string, string>;

useRouteParams

Type: useRouteParams: (defaultValues?: RouteObject): [RouteObject, DispatchState<RouteObject>]

Use to sync the URL Parameters with you component.

This custom hook returns an array with two elements:

  • The first element is a string to string object, when the key is the route param name, and the value is the value of this param.

  • The second element is a function to update the route with new string to string object. Like in useState, you can set a new object, or set a function to transaform the prev state to a new one.

Updating the route will push the updated route to the history.

The params object will be reactive to the route. It means the any time the route changed, the params object (the first element from useParamsAsState) will change according to the route and will render the component.

The update function (the second element from useParamsAsState) will change the route, and it will cause an update in the params object, respectively.

Note

To use Route Params, you have to declare the params with the React Router API.

useQueryString

Type: useQueryString: (defaultValues?: RouteObject): [RouteObject, DispatchState<RouteObject>]

Use to sync the Query Parameters with you component.

This hook works just like useParamsAsState, except you don't need to declare any special route in the React Router. You can use this hook in any component, down in the tree, as long as there is a Router somewhere up in the tree.

Updating the route will replace the updated route to the history.

useQueryStringKey

Type: useQueryStringKey: (key: string, defaultValue?: string): [string | undefined, Dispatch<SetStateAction<string>>]

Instead of managing the whole query object, you can use this to get a reactive reference to the value itself.

Example:

// URL: /?foo=bar
import * as React from "react";
import { useQueryStringKey } from "use-route-as-state";

const Example = () => {
  const [foo, setFoo] = useQueryStringKey("foo");

  return (
    <div>
      <input value={query} onChange={({ target }) => setFoo(target.value)} />
    </div>
  );
};

useUrlState

type UrlState = {
  params: RouteObject;
  query: RouteObject;
};

Type: useUrlState: (defaultValues?: UrlState): [UrlState, DispatchState<UrlState>]

Due to limitations in React Router, and React itself, you can't use different hooks here together during one render cycle.

In order to solve that, you can use this hook to control both route params and query string at once.

Development

Local development is broken into two parts (ideally using two tabs).

First, run rollup to watch your src/ module and automatically recompile it into dist/ whenever you make changes.

yarn start # runs rollup with watch flag

The second part will be running the example/ create-react-app that's linked to the local version of your module.

# (in another tab)
cd example
yarn start # runs create-react-app dev server

Now, anytime you make a change to your library in src/ or to the example app's example/src, create-react-app will live-reload your local dev server so you can iterate on your component in real-time.


This hook is created using create-react-hook.

use-route-as-state's People

Contributors

baruchiro avatar cxlucas avatar dependabot[bot] avatar ptmkenny avatar semantic-release-bot avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar

use-route-as-state's Issues

Add support for clear rest of params

I want to add support of when you update the first RouteParam, it will reset the rest of the params.

For example, say we have this route:

/item/:order?/:product?/:type?/:id?

And now I'm in this route with all params: /item/321/apple/high/123, and I'm changing the order and the product, I want the type and id to reset because I don't even know if they exist in the current order/product, so when I changing the order and product, the URL should update to /item/{newOrder}/{newProduct}.

I'm thinking of getting a sorted array (just an array with a meaning of its sort) in the hook function and find the latest item when updating, and clear the values of the rest after the last.

Default values without change the route

As we using the route as state, we need a way to defines a default value.

When I'm saying "default value" and I'm using the route, I mean whenever the route is empty (for example, no Query String), we need to get the default value from our custom hook.

The problem is to do that without changing the route, and without override the default value with empties values from route.

Help Needed.

Can re-render be made independent, so that multiple hook calls re-render only the affected param?

Issue description
My app has an horizontal split screen, the two areas have different tabs that slide different sections, tabs are independent,

I would like to persist and read params so that a URL can be shared with the correct sections, or to better handle refreshing.
I have noticed that both useQueryStringKey and useQueryString make the whole page re-render.
Is there a way to avoid that?
Ideally each portion should re-render independently.

To clarify, I've tried co-locating each section into its own component:

  • A page component renders and
  • Each section has its own useQueryStringKey/useQueryString
    Β 

What's the expected result?
Setting top tab (to navigate a different slide on the top part) re-renders only top section..
Β 

What's the actual result?
Setting top tab (to navigate a different slide on the top part) re-renders also bottom section.

Create a release branch

With the current implementation of SemanticRelease (documented here), to publish a version with multiple recorded changes (like a new feature and dependencies upgrades), you have to develop those two in the same PR.

This is because the SemanticRelease pipeline is triggered when pushing to master.

We need to trigger it in another way, maybe by triggering it on another branch, maybe manual, any idea is welcome.

Add support for repeating query params (arrays)

Hi,

I was looking to be able to work with query params easily, and also be able to update only certain params. I first wrote something small myself, but wanted to see if there would be something better. This package looks good, but one feature we do require for our functionality is the usage of repeating query params, which resolves to arrays. I didn't find this in the code, and I think this feature is missing.

It's a pity that react-router itself doesn't have such API's, because updating some params is something done a lot while using a web application that use the route as main state to start off.

'%' in URL leads to exception

Reproduce: setQuery({foo: "%bar"}). My expectation would be "...?foo=%25bar", but it leads to an exception.
It seems to be an issue with the encoding/decoding. Please let me know if my expectations are wrong.
Thank you for maintaining this library!

The automated release is failing 🚨

🚨 The automated release from the master branch failed. 🚨

I recommend you give this issue a high priority, so other packages depending on you can benefit from your bug fixes and new features again.

You can find below the list of errors reported by semantic-release. Each one of them has to be resolved in order to automatically publish your package. I’m sure you can fix this πŸ’ͺ.

Errors are usually caused by a misconfiguration or an authentication problem. With each error reported below you will find explanation and guidance to help you to resolve it.

Once all the errors are resolved, semantic-release will release your package the next time you push a commit to the master branch. You can also manually restart the failed CI job that runs semantic-release.

If you are not sure how to resolve this, here are some links that can help you:

If those don’t help, or if this issue is reporting something you think isn’t right, you can always ask the humans behind semantic-release.


Invalid npm token.

The npm token configured in the NPM_TOKEN environment variable must be a valid token allowing to publish to the registry https://registry.npmjs.org/.

If you are using Two Factor Authentication for your account, set its level to "Authorization only" in your account settings. semantic-release cannot publish with the default "
Authorization and writes" level.

Please make sure to set the NPM_TOKEN environment variable in your CI with the exact value of the npm token.


Good luck with your project ✨

Your semantic-release bot πŸ“¦πŸš€

Setting default values in URL

Use case

I would like to uniquely sync the state with the URL (modulo param permutation). This is not the case when using default, the same state can lead to two distinct url.

Current behavior

For instance on demo page (https://github.com/baruchiro/use-route-as-state), const [foo, setFoo] = useQueryStringKey('foo', 'bar'), the default value of foo (bar) does not show up in the URL on page load. Then after manual update is does.

First page load:
Screenshot 2021-09-26 at 11 56 10
Screenshot 2021-09-26 at 12 03 15

After changing the foo in input and setting it back to bar.
Screenshot 2021-09-26 at 11 56 16
Screenshot 2021-09-26 at 11 56 05

Any reco on how to make sure the URL is https://baruchiro.github.io/use-route-as-state/?foo=bar on page load?

Set all defaults explicitly before the updated param

If I have this URL schema /item/:order?/:product?/:type?/:id?, and all the params except id are with default values.

When I updating the id, it will generate /item/{myID}.

Need to explicitly set the default values that come before the update.

See #4 because it is also about the order of the params.

ChainAlert: Dependency "lru-cache" version 7.4.0 has new "prepare" script

ChainAlert has detected a new "prepare" script in lru-cache in one of your project's dependencies - a suspicious new release of "lru-cache" version "7.4.0" on npm.
This script runs automatically upon installing the package.

scripts section from the package.json file of "lru-cache" version "7.4.0":

{
    "prepare": "webpack-cli -o bundle ./index.js --node-env production",
    "build": "npm run prepare",
    "presize": "npm run prepare",
    "test": "tap",
    "snap": "tap",
    "size": "size-limit",
    "preversion": "npm test",
    "postversion": "npm publish",
    "prepublishOnly": "git push origin --follow-tags"
}

We've already alerted lru-cache maintainers on https://github.com/chainalert-bot/private_alerts/issues/39

This is an automated notification by ChainAlert, a free service for the Open Source community by Checkmarx.
For any questions please contact us at [email protected]

badge

Setting both query string key and route params in one render/effect does not work.

Steps to reproduce

  1. Run the following app
  2. Go to /test/old-slug
  3. Observe the param is added but slug is still old: /test/old-slug?param=new-param
  4. If you reverse the order of setSlugs/setParam, the opposite happens - slug is updated but param not.
import {useEffect} from "react";
import {Route, BrowserRouter, Switch} from "react-router-dom";
import {useQueryStringKey, useRouteParams} from "use-route-as-state";

function TestSlug() {
    const [slugs, setSlugs] = useRouteParams();
    const [param, setParam] = useQueryStringKey('param')

    useEffect(() => {
        setSlugs({slug: 'new-slug'});
        setParam('new-param');
    }, [])

    return <span> Slug: {slugs.slug} Param: {param}</span>
}

function App() {
    return (
            <BrowserRouter>
                <Switch>
                    <Route path="/test/:slug"><TestSlug /></Route>
                </Switch>
            </BrowserRouter>
    )
}

They affect the same underlying state (URL string) so this might be actually a result how React works.
A great workaround would be to provide 'useUrlState' allowing to set both route params and query string keys through single setter.

Can't use with npm 8 and react 17

When I try to install in a react 17 project and npm 8, I get this:

npm ERR! While resolving: 
npm ERR! Found: [email protected]
npm ERR! node_modules/react
npm ERR!   react@"^17.0.2" from the root project
npm ERR!
npm ERR! Could not resolve dependency:
npm ERR! peer react@"^16.0.0" from [email protected]
npm ERR! node_modules/use-route-as-state
npm ERR!   use-route-as-state@"^5.1.1" from the root project

I assume this is because peerDependencies in package.json still lists ^16.0.0 as the react dependency. I have to install with ---legacy-peer-deps to get it to install. Any chance we can get that fixed?

react-router-dom v6 support?

✘ [ERROR] No matching export in "node_modules/react-router-dom/index.js" for import "useRouteMatch"

    node_modules/use-route-as-state/dist/index.es.js:2:22:
      2 β”‚ import { useLocation, useRouteMatch, useHistory, generatePath } from 'react-r..$
        β•΅                       ~~~~~~~~~~~~~

✘ [ERROR] No matching export in "node_modules/react-router-dom/index.js" for import "useHistory"

    node_modules/use-route-as-state/dist/index.es.js:2:37:

https://reactrouter.com/docs/en/v6/upgrading/v5

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    πŸ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. πŸ“ŠπŸ“ˆπŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❀️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.