Code Monkey home page Code Monkey logo

use-local-storage's Introduction

useLocalStorage React hook

A flexible React Hook for using Local Storage.

Test Status Codecov Status


useLocalStorage React hook demo


Features

✅ Persists data to local storage with an interface similar to the React useState hook

✅ Works with any hooks-compatible React version

✅ Works with SSR

✅ Syncs data between components in the same or different browser tabs

Installation

Install with npm

npm i use-local-storage

Install with yarn

yarn add use-local-storage

Basic Usage

In its most basic form, the useLocalStorage hook just needs the Local Storage key you wish to use. However, it's advised that you also provde a default value as a second argument in the event that they key does not yet exist in Local Storage.

The following usage will persist the username variable in a "name" key in Local Storage. It will have a default/initial value of an empty string "". This default value will only be used if there is no value already in Local Storage, moreover setting the variable username to undefined will remove it from Local Storage.

import useLocalStorage from "use-local-storage";

function MyComponent() {
  const [username, setUsername] = useLocalStorage("name", "");

  return (
    <>
      <input
        value={username}
        onChange={(e) => {
          setUsername(e.target.value);
        }}
      />
      <button
        onClick={() => {
          setUsername(undefined);
        }}
      >
        Remove Username
      </button>
    </>
  );
}

Note: By default, the useLocalStorage hook uses JSON.stringify and JSON.parse to serialize and parse the data, respectively. A custom serializer and/or parser can be configured if desired (discussed below in the Advanced Usage section).

Typescript Use

The type of username will be inferred from your default value. In this case, the type of string will be inferred.

If you use useLocalStorage without providing a default value, or you simply want to specify that username is actually of a different type, you should pass the type of your data as a generic:

import useLocalStorage from "use-local-storage";

function MyComponent() {
  const [username, setUsername] = useLocalStorage<string>("name");

  return (
    <>
      <input
        value={username}
        onChange={(e) => {
          setUsername(e.target.value);
        }}
      />
      <button
        onClick={() => {
          setUsername(undefined);
        }}
      >
        Remove Username
      </button>
    </>
  );
}

Advanced Usage / Options

the useLocalStorage hook takes an optional third options argument. This allows you to configure a custom serializer and/or parser if you need to use something other than JSON.stringify and JSON.parse. The options object also has a logger key to log an errors caught in the hook. You can also disable the cross-context synchronization by setting syncData to false.

const options = {
  serializer: (obj) => {
    /* Serialize logic */
    return someString;
  },
  parser: (str) => {
    /* Parse logic */
    return parsedObject;
  },
  logger: (error) => {
    // Do some logging
  },
  syncData: false, // You can disable cross context sync
};

const [data, setData] = useLocalStorage("data", { foo: "bar" }, options);

Attribution

Storage icon made by DinosoftLabs from www.flaticon.com

use-local-storage's People

Contributors

atifcppprogrammer avatar dependabot[bot] avatar franciscop avatar guoyunhe avatar nas5w avatar shadowlauch 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  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  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar

use-local-storage's Issues

Expand options with example for saving a Date object with Typescript example

Is your feature request related to a problem? Please describe.
I'm working on using this package for the first time and can't figure out the parser options for a Date object in Typescript

Describe the solution you'd like
Expand the Readme or docs to give options for storing more distinct types

Describe alternatives you've considered
I tried:

  const [birthdate, setBirthdate] = useLocalStorage<Date>(
    'birthdate',
    new Date('2005-04-29')
  )

Which returned a string. That was to be expected.

Then I added:

const birthdateOptions = {
  serializer: (obj: any): string => {
    /* Serialize logic */
    console.log(obj, typeof obj)
    return obj.toISOString().split('T')[0]
  },
  parser: (str: any): Date => {
    /* Parse logic */
    console.log(str, typeof str)
    return new Date(str)
  },
}

Which had to use any cause I could not take Date or string or it would cause a mismatch with the hook.

Additional context
I'm looking to understand this package better and make use of it correctly. So asking for some help here and some improved docs to help the next person.

Invalid hook call. Hooks can only be called inside of the body of a function component

Describe the bug
Following error message it's displayed in the browser

Error: Invalid hook call. Hooks can only be called inside of the body of a function component. This could happen for one of the following reasons:

  1. You might have mismatching versions of React and the renderer (such as React DOM)
  2. You might be breaking the Rules of Hooks
  3. You might have more than one copy of React in the same app
    See https://reactjs.org/link/invalid-hook-call for tips about how to debug and fix this problem.

To Reproduce
use the react hook on any component

Expected behavior
Should work properly without forcing to use rect 17, react hooks works from React 16.8

Additional context
Similar libraries does not list react as a dependency, I wonder if that's a best practice

https://www.npmjs.com/package/@rooks/use-localstorage
https://www.npmjs.com/package/react-use-localstorage

Add CONTRIBUTING.md

Add CONTRIBUTING.md

Recommend using a template. Nothing too fancy but should outline how to contribute to the repo, including:

  • Creating an issue before doing a PR using the Issue Template
  • Getting approval for the issue
  • Doing a PR using the Pull Request Template

Stale keys and default values

Describe the bug
The keys, default values, etc. all become stale when they change (using the old ones instead of the new ones), since they are not being depended properly by the dependencies array.

To Reproduce
Run the tests in here:
#26

Expected behavior
If you change the key, the hook uses the new one instead of the old one. Same for the default value.

Screenshots
image

Desktop (please complete the following information):
Any

Smartphone (please complete the following information):
Any

Additional context
Add any other context about the problem here.

The `setValue` and `setKey` state-setters do not take callback functions

Is your feature request related to a problem? Please describe.
The setValue and setKey state-setters do not take callback functions.

Describe the solution you'd like
To make the hook as React-y as possible, these state-setters should optionally take a callback function.

Describe alternatives you've considered
Leaving as-is, but that could cause async issues and potentially stale data

SSR Framework says window is undefined

Describe the bug
I'm using this on Next.js and it seems that window is called when it wasn't ready in the Next.js's server environment/build time

To Reproduce
Steps to reproduce the behavior:
just install and use it on nextjs (or anything with ssr/ssg method)

Expected behavior
I think you can prevent calling before windows object is ready, something like : if (window)

Screenshots
https://ibb.co/4Jvw0j9
https://ibb.co/4Jvw0j9

Remove key when setting value to undefined

I'm expecting that a key I've setted with a value of undefined to be removed from the localStorage.

Give the following:

import useLocalStorage from "use-local-storage";

function App() {
  const [username, setUsername] = useLocalStorage("name", "");

  return (
    <>
      <input
        value={username}
        onChange={(e) => {
          setUsername(e.target.value);
        }}
      />
    <button onClick={() => setUsername(undefined)}>Clear localStorage</button>
    </>
  );
}

Once I click the "Clear localStorage" button, I expect the "name" key to be removed from the local storage. The observed result is that the name key gets the value undefined in the storage.

image

Here's a Codesandbox that reproduces this behavior.

Add Code of Conduct

Add CODE_OF_CONDUCT.md file.

Recommend using the "Contributor Covenant" template unless there's a good reason to use something else.

Add storage event listener to keep data synced

Is your feature request related to a problem? Please describe.
In some cases (e.g., using the hook in multiple tabs) data can become out of sync from local storage.

Describe the solution you'd like
Add a window event listener on the storage action that sets the value state on change.

Describe alternatives you've considered
none

State not syncing across components

Describe the bug
When you modify localStorage from another tab, the state updates correctly. However when you modify state from another component, an update is not triggered. This library lacks a pub/sub to make it possible.

To Reproduce
Click one button here. The other should update as well (but it doesn't):
https://codesandbox.io/s/xenodochial-herschel-xptrbl?file=/src/App.js

Expected behavior
The state syncs for the same component (works), across components (bug) and across tabs (works). Only across components is broken now, which is very odd.

Screenshots
image

Desktop (please complete the following information):
All

Smartphone (please complete the following information):
All

Additional context
I'd recommend a simple pub/sub system across keys and using the provided callbacks.

Add ability to specify the type of new key's data when you set a new localstorage key

Is your feature request related to a problem? Please describe.
When using setKey, you can't currently change the type of the data associated with that key.

Describe the solution you'd like
A way to specify the type of the new key's data, if that's possible

Describe alternatives you've considered
Just not making it possible (current state)

Additional context
Probably just above my ability at this point, folks with more Typescript expertise needed!

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.