Giter VIP home page Giter VIP logo

react-native-use-persist-storage's Introduction

React Native Hooks - usePersistStorage

Persist and rehydrate a context store by React Hooks

  • An asynchronous persist storage
  • Support sensitive info both on iOS & Android
  • Migration function

npm version

Install

Install react-native-use-persist-storage

$ yarn add react-native-use-persist-storage

Install @react-native-async-storage/async-storage, react-native-sensitive-info (see peerDependencies)

$ yarn add react-native-sensitive-info @react-native-async-storage/async-storage

If RN < 0.60, link dependencies

$ react-native link react-native-sensitive-info
$ react-native link @react-native-async-storage/async-storage

Note: For IOS project using pods, run: $ cd ios/ && pod install

Peer Dependencies

Note: react-native-use-persist-storage requires the following peer dependencies:


Usage

Make sure you know how React Hooks works, and you can use it just same as useState.

Basic Usage

// User.js
import { usePersistStorage } from "react-native-use-persist-storage";

const createDefaultUser = () => ({
  name: ""
});

const User = props => {
  const [user, setUser, restored] = usePersistStorage(
    "@User",
    createDefaultUser
  );
  if (restored) return <Text>loading...</Text>;
  return <Text>{user.name}</Text>;
};

Context Usage

If you want a light-weight global state management solution in react, try using Context.

// contexts/user.js
import { createContext } from 'react'
import { usePersistStorage } from 'react-native-use-persist-storage'

const createDefaultUser = () => ({
  name: '',
});

const UserContext = createContext(...);

const UserProvider = props => {
  const [user, setUser, restored] = usePersistStorage('@User', createDefaultUser);

  // anything you need...

  return (
    <UserContext.Provider value={
      { user, updateUser: setUser, restored }
      // or like this
      // [ user, updateUser: setUser, restored ]
    }>
      {props.children}
    </UserContext.Provider>
  );
};
// GlobalStateProvider.ts
const GlobalStateProvider = ({ children }) => (
  <OtherContextProvider>
    <UserProvider>
      {children}
    </UserProvider>
  </OtherContextProvider>
)

// App.js
const App = () => {
  return (
    <GlobalStateProvider>
      <Root />
    </GlobalStateProvider>
  );
};

Recommend use: createPersistContext

API

usePersistStorage(key, initialValue, options?)

  • arguments
    • key: async storage key
    • initialValue: initial value
    • options: set options debug, persist, version, migrate, sensitive.
options (see)
  • debug: call console.debug when any persist storage action.
    • default: false
  • persist: set false, it will same as useState
    • default: true
  • version: storage version, set with migrate function
    • default: 0
  • migrate: set migrate function, see how to use createMigrate
    • default: null
  • sensitive: pass config options, it will use react-native-sensitive-info to store your data.
    • default: false

createPersistContext

It is a simple built-in util function for easy use. See

// contexts/user.js
import { createPersistContext } from 'react-native-use-persist-storage';

export default createPersistContext({
  storageKey: '@User',
  defaultData: {
    name: 'Awesome!'
  },
  options: { ... }
});

// App.js
import User from './contexts/user';
const App = () => {
  return (
    <User.Provider>
      <Root />
    </User.Provider>
  );
};

// Component.js
import User from './contexts/user';

const Component = () => {
  const [user, setUser] = User.useData();
  return ...
};

Or, you can create a hook to customize

// hooks/useUser.js
import User from './contexts/user';

const useUser = () => {
  const [user, setUser] = useContext(User.Context);
  const setName = () => ...
  const setEmail = () => ...
  return {
    user,
    setName,
    setEmail,
    setUser,
    // anything ...
  };
};

const Component = () => {
  const { user, ... } = useUser();
  ...
}

createMigrate

Use like redux migration

import { createMigrate, usePersistStorage } from 'react-native-use-persist-storage';

const [user, setUser, restored] = usePersistStorage(
  '@User',
  defaultUser,
  {
    version: 2,
    migrate: createMigrate(
      {
        1: state => {
          // ...
        },
        2: state => ({
          // ...
        }),
        
      },
    ),
  },
)

setPersistStorageDefaults

You can control all default options when app initialized.(see)

  • open debug log:
setPersistStorageDefaults({ debug: true });
  • remove all stored values in persistent storage:
setPersistStorageDefaults({ persist: false });

react-native-use-persist-storage's People

Contributors

chihsuan avatar dependabot[bot] avatar dsernst avatar tsehang avatar yarapolana 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

Watchers

 avatar  avatar  avatar  avatar

react-native-use-persist-storage's Issues

Add Provider instructions to createPersistContext docs

The createPersistContext helper function is great. But following the docs, I was stuck for about 30 minutes trying to debug what was missing, why weren't my changes updating the state?

Eventually I realized it was because I hadn't added <PersistContext.Provider> around my app. I know it does mention this in the "Context Usage" section, but the docs make it seem like createPersistContext handles all that boilerplate automatically. It wasn't obvious w/o serious digging to figure out what was missing.

usePersistStorage.d.ts

Line 12: Has a typo 'type'
it's set to false when it should be boolean
sensitive?: false | RNSensitiveInfoOptions;
should be
sensitive?: boolean | RNSensitiveInfoOptions;

Setting `sensitive: true` yields type error

Hey there,

I don't know the best way to help debug this, but I have found on my end that this does not work as expected:

const [userData, setUserData, userIsReady] = usePersistStorage(
    USER_PERSISTENCE_KEY,
    () => {
      user: null;
    }, //default value
    {
      version: USER_PERSISTENCE_VERSION,
      persist: true,
      sensitive: true,
    }
  );

if I remove sensitive: true, no error is raised, so it must be that setting it to use sensitive storage causes:

JSON value '1' of type NSNumber cannot be converted to NSDictionary

+[RCTConvert NSDictionary:]
    RCTConvert.m:58
__41-[RCTModuleMethod processMethodSignature]_block_invoke_16
-[RCTModuleMethod invokeWithBridge:module:arguments:]
facebook::react::invokeInner(RCTBridge*, RCTModuleData*, unsigned int, folly::dynamic const&)
facebook::react::RCTNativeModule::invoke(unsigned int, folly::dynamic&&, int)::$_0::operator()() const
invocation function for block in facebook::react::RCTNativeModule::invoke(unsigned int, folly::dynamic&&, int)
_dispatch_call_block_and_release
_dispatch_client_callout
_dispatch_lane_serial_drain
_dispatch_lane_invoke
_dispatch_workloop_worker_thread
_pthread_wqthread
start_wqthread

I have "react-native-sensitive-info": "^5.5.8" and the pod is installed. resetting the npm cache and rebuilding the app has no effect.

Is there any more information I can give to help figure out what I'm doing wrong, or whether this is a bug?

Async setState function?

Now setState will immediately execute, then background update AsyncStorage.
It has a problem that we don't know when the AsyncStorage finish updating storage.

In general, storage state(context) might not be frequently updated.
But, if update frequently it may happen race condition, then lead to an un-predictable bug.

Looks like first we can let setState be async, so that we can control update sequence in this use-case?

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.