Save and load the Redux state with ease

Overview

redux-storage

build dependencies devDependencies

license npm version npm downloads Code Climate

Save and load the Redux state with ease.

Moved to the react-stack organisation

My focus has left the node / react ecosystem and this module has got a new home over at react-stack!

Features

  • Flexible storage engines
  • Flexible state merger functions
  • Storage engines can be async
  • Load and save actions that can be observed
    • SAVE: { type: 'REDUX_STORAGE_SAVE', payload: /* state tree */ }
    • LOAD: { type: 'REDUX_STORAGE_LOAD', payload: /* state tree */ }
  • Various engine decorators
  • Black- and whitelist actions from issuing a save operation

Installation

npm install --save redux-storage

And you need to install at least one redux-storage-engine, as redux-storage is only the "management core".

Usage

import * as storage from 'redux-storage'

// Import redux and all your reducers as usual
import { createStore, applyMiddleware, combineReducers } from 'redux';
import * as reducers from './reducers';

// We need to wrap the base reducer, as this is the place where the loaded
// state will be injected.
//
// Note: The reducer does nothing special! It just listens for the LOAD
//       action and merge in the provided state :)
// Note: A custom merger function can be passed as second argument
const reducer = storage.reducer(combineReducers(reducers));

// Now it's time to decide which storage engine should be used
//
// Note: The arguments to `createEngine` are different for every engine!
import createEngine from 'redux-storage-engine-localstorage';
const engine = createEngine('my-save-key');

// And with the engine we can create our middleware function. The middleware
// is responsible for calling `engine.save` with the current state afer
// every dispatched action.
//
// Note: You can provide a list of action types as second argument, those
//       actions will be filtered and WON'T trigger calls to `engine.save`!
const middleware = storage.createMiddleware(engine);

// As everything is prepared, we can go ahead and combine all parts as usual
const createStoreWithMiddleware = applyMiddleware(middleware)(createStore);
const store = createStoreWithMiddleware(reducer);

// At this stage the whole system is in place and every action will trigger
// a save operation.
//
// BUT (!) an existing old state HAS NOT been restored yet! It's up to you to
// decide when this should happen. Most of the times you can/should do this
// right after the store object has been created.

// To load the previous state we create a loader function with our prepared
// engine. The result is a function that can be used on any store object you
// have at hand :)
const load = storage.createLoader(engine);
load(store);

// Notice that our load function will return a promise that can also be used
// to respond to the restore event.
load(store)
    .then((newState) => console.log('Loaded state:', newState))
    .catch(() => console.log('Failed to load previous state'));

Details

Engines, Decorators & Mergers

They all are published as own packages on npm. But as a convention all engines share the keyword redux-storage-engine, decorators can be found with redux-storage-decorator and mergers with redux-storage-merger. So it's pretty trivial to find all the additions to redux-storage you need 😄

Actions

redux-storage will trigger actions after every load or save operation from the underlying engine.

You can use this, for example, to display a loading screen until the old state has been restored like this:

import { LOAD, SAVE } from 'redux-storage';

function storageAwareReducer(state = { loaded: false }, action) {
    switch (action.type) {
        case LOAD:
            return { ...state, loaded: true };

        case SAVE:
            console.log('Something has changed and written to disk!');

        default:
            return state;
    }
}

Middleware

If you pass an array of action types as second argument to createMiddleware, those will be added to a internal blacklist and won't trigger calls to engine.save.

import { createMiddleware } from 'redux-storage'

import { APP_START } from './constants';

const middleware = createMiddleware(engine, [ APP_START ]);

If you want to whitelist all actions that are allowed to issue a engine.save, just specify them as third argument.

import { createMiddleware } from 'redux-storage'

import { SHOULD_SAVE } from './constants';

const middleware = createMiddleware(engine, [], [ SHOULD_SAVE ]);

License

The MIT License (MIT)

Copyright (c) 2015 Michael Contento

Permission is hereby granted, free of charge, to any person obtaining a copy of
this software and associated documentation files (the "Software"), to deal in
the Software without restriction, including without limitation the rights to
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
the Software, and to permit persons to whom the Software is furnished to do so,
subject to the following conditions:

The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
Comments
  • State is not updating on load

    State is not updating on load

    I am finding that my state is not being populated correctly when the REDUX_STORAGE_LOAD action is dispatched -

    63053a8e-63d3-11e6-986d-cfee2bfc9158

    I've ruled out a save occurring before load by whitelisting just one action.

    My storage reducer is simply -

    import { LOAD, SAVE } from 'redux-storage';
    
    export default function storeageAwareReducer(state = { loaded: false }, action) {
      switch (action.type) {
        case LOAD:
          return { ...state, loaded: true };
    
        case SAVE:
          console.log('Something has changed and written to disk!');
    
        default:
          return state;
      }
    }
    

    My store setup is very standard and follows the example in the readme and I am using the redux-storage-engine-reactnativeasyncstorage engine -

    import * as storage from 'redux-storage'
    import createEngine from 'redux-storage-engine-reactnativeasyncstorage';
    import { createStore, applyMiddleware } from 'redux';
    import thunk from 'redux-thunk';
    import createLogger from 'redux-logger';
    import { APP } from '../configs/index';
    import api from 'CookAndCount/app/middleware/api';
    
    import rootReducer from '../reducers/index';
    
    // Wrap reducer for use with redux-storage
    const reducer = storage.reducer(rootReducer);
    
    const logger = createLogger();
    
    // Create a storage engine for AsyncStorage
    let storage_key = `cook-and-count-${APP.STORAGE_SUFFIX}`;
    
    const engine = createEngine(storage_key);
    
    // Create middleware - thunk and storage
    const middleware = [thunk, api, logger, storage.createMiddleware(engine)];
    
    // Create store with middleware applied
    const store = createStore(rootReducer, applyMiddleware(...middleware));
    
    // Load in previous app state
    const load = storage.createLoader(engine);
    
    load(store)
    
    export default store;
    

    When I listen to the promise I am getting the intended state and no errors -

    load(store)
      .then((newState) => console.log('Loaded state:', newState))
      .catch(() => console.log('Failed to load previous state'));
    
    opened by adambutler 13
  • Merge() from lodash causes warnings in Immutable.js

    Merge() from lodash causes warnings in Immutable.js

    I'm using Immutable decorator to load state data with localStorage engine. But on initial load I get a bunch of warnings from Immutable library:

    iterable.length has been deprecated, use iterable.size or iterable.count(). This warning will become a silent error in a future version. Error
        at src_Map__Map.Object.defineProperty.get (webpack:///./~/immutable/dist/immutable.js?:4632:21)
        at pathKey (webpack:///./~/lodash/index.js?:2452:51)
        at isArrayLike (webpack:///./~/lodash/index.js?:4075:40)
        at baseMergeDeep (webpack:///./~/lodash/index.js?:2416:13)
        at eval (webpack:///./~/lodash/index.js?:2366:11)
        at arrayEach (webpack:///./~/lodash/index.js?:1289:13)
        at baseMerge (webpack:///./~/lodash/index.js?:2358:7)
        at eval (webpack:///./~/lodash/index.js?:3024:13)
        at eval (webpack:///./~/lodash/index.js?:8152:31)
        at exports.default (webpack:///./~/redux-storage/lib/reducer.js?:13:76)
    immutable.js:4637 iterable.length has been deprecated, use iterable.size or iterable.count(). This warning will become a silent error in a future version. Error
        at src_Map__Map.Object.defineProperty.get (webpack:///./~/immutable/dist/immutable.js?:4632:21)
        at isTypedArray (webpack:///./~/lodash/index.js?:8998:51)
        at baseMergeDeep (webpack:///./~/lodash/index.js?:2416:60)
        at eval (webpack:///./~/lodash/index.js?:2366:11)
        at arrayEach (webpack:///./~/lodash/index.js?:1289:13)
        at baseMerge (webpack:///./~/lodash/index.js?:2358:7)
        at eval (webpack:///./~/lodash/index.js?:3024:13)
        at eval (webpack:///./~/lodash/index.js?:8152:31)
        at exports.default (webpack:///./~/redux-storage/lib/reducer.js?:13:76)
        at dispatch (webpack:///./~/redux/lib/createStore.js?:120:22)
    immutable.js:4637 iterable.length has been deprecated, use iterable.size or iterable.count(). This warning will become a silent error in a future version. Error
        at src_Map__Map.Object.defineProperty.get (webpack:///./~/immutable/dist/immutable.js?:4632:21)
        at pathKey (webpack:///./~/lodash/index.js?:2452:51)
        at isArrayLike (webpack:///./~/lodash/index.js?:4075:40)
        at isArguments (webpack:///./~/lodash/index.js?:8469:37)
        at isPlainObject (webpack:///./~/lodash/index.js?:8924:77)
        at baseMergeDeep (webpack:///./~/lodash/index.js?:2421:18)
        at eval (webpack:///./~/lodash/index.js?:2366:11)
        at arrayEach (webpack:///./~/lodash/index.js?:1289:13)
        at baseMerge (webpack:///./~/lodash/index.js?:2358:7)
    

    I guess, this is happening, because merge() function on lodash is used https://github.com/michaelcontento/redux-storage/blob/master/src/reducer.js#L8 when LOAD action being handled and it uses .length somehow.

    What we can do with it?

    opened by romanenko 13
  • How can I clear the saved state?

    How can I clear the saved state?

    This is an awesome solution for me, thanks!

    I am using this with react-native and I'm wondering how to clear the state so i can start fresh if i mess something up in the state tree

    waiting for feedback 
    opened by kevando 8
  • failing to load initial state, but actually is loading initial state, but then causing other issues

    failing to load initial state, but actually is loading initial state, but then causing other issues

    For whatever reasons, the catch statement of the promise returned by load is being called, but the previous state is in fact loading. That's not the real issue that's causing me problems though--Redux's connect mapStateToProps functions aren't being called again when the state changes. I've pintpointed this as a Redux Storage issue because when I remove the load call of Redux Storage, everything works.

    So my thinking is that it's "failing" not so much in that the loading of previous state fails, but failing in some other regards with how it interfaces with the rest of Redux. What are the common reasons the promise's catch would be triggered?

    opened by faceyspacey 7
  • Reloading causes

    Reloading causes "Warning: You cannot PUSH the same path using hash history" with react-router-redux

    This is a bug that arises from using popular packages together. I'm posting the bug here, and hoping you can cooperate with the involved parties.

    If a user reloads an app that uses redux-storage & redux-storage-engine-localstorage & react-router & react-router-redux then the app will eventually complain with the error Warning: You cannot PUSH the same path using hash history.

    Cause: React-storage triggers react-router-redux's enhanced react-router history, since it's causing a change in state. This in turns causes a history.push(...) to the restored URL, which is the same since it's a reload of the same page, thus causing the warning.

    This issue doesn't seem to be directly addressed in the other projects since it's caused by using this plugin which automatically loads router state. Note that loading the state before enhanced router will avoid this bug, but then redux-storage fails to restore previous state on the second reload.

    waiting for feedback 
    opened by scarlac 7
  • Array default values

    Array default values

    Hi! I have a test reducer: myReducer = (state = { arr: [1, 2, 3] }, action) => action.type == 'TEST' ? { arr: [5] } : state It's save to store correctly after dispatch: { arr: 5 } But after load it's has a value { arr: [5, 2, 3] }. Lo-dash _.merge problem.

    waiting for feedback 
    opened by omsk359 7
  • Return new state object on reducer LOAD

    Return new state object on reducer LOAD

    Reducer should, on load, return a NEW state object, instead of modifying state. Without this, it doesn't pass new state (reliably, at least) into components after load.

    opened by skevy 7
  • allow whitelist to be a function

    allow whitelist to be a function

    A pretty standard practice is for 3rd party reducers to use a prefix for all of their actions (eg redux-form/DESTROY). In my use case, I'd like to disallow every action triggered by a certain 3rd party reducer (eg every action that begins with redux-form/) .

    Today, I'd have to know & list every single action that a 3rd party reducer can create. That's a long list. Plus, I run the risk of the list going stale when my 3rd party package updates or changes a constant.

    I can accomplish what I want by iterating over the entire blacklist & checking to see if my blacklisted substring is found in each entry. However, your logic may differ.

    That's why if we allow the whitelist to be a function, everyone wins. For example, I'd write something like this:

    const whitelistFn = type => {
        const blacklistPrefixes = ['redux-form/', '@@router/'];
        for (let i = 0; i < blacklistPrefixes.length; i++) {
            const prefix = blacklistPrefixes[i];
            if (type.indexOf(prefix) !== -1) {
                return false;
            }
        }
        return true;
    }
    

    And you can use whatever logic you like. The idea is borrowed from webpack, where a bunch of config fields can either be an array or a function.

    opened by mattkrick 6
  • setTimeout around engine.save

    setTimeout around engine.save

    We are currently using redux-storage and are experiencing that it slows down our app quite significantly due to many writes (debouncing didn't help in our case). As a small experiment we put a setTimeout(.., 1000) around the engine.save() command because we only want to save stuff as soon as there is no UI thread doing anything. And lo and behold, that surely sped things up quite a bit.

    Would it be possible to have this as a feature and if not, are there complications?

    Cheers,

    Danny

    waiting for feedback 
    opened by dannybloe 6
  • Versioned storage with migrations

    Versioned storage with migrations

    Hi,

    I am just curious if you thought about store migrations? What if we change structure? I think it should be responsibility of every reducer reviver.

    enhancement help wanted 
    opened by steida 6
  • Splitting the decorators from the core

    Splitting the decorators from the core

    Right now, when using this package without immutable, it will still require immutablejs which is quite big.

    Each decorators should be required separately or be in its own package.

    enhancement 
    opened by mathieudutour 5
  • Redux 4.0 support?

    Redux 4.0 support?

    opened by alexey-pelykh 2
  • Not all actions are being saved.

    Not all actions are being saved.

    Despite the setup as below with no blacklisted or whitelisted actions, once I dispatch sertain actions all saving stops for the entire app.

    const reducer = storage.reducer(combineReducers({
      menu: menuReducer,
      axios: axiosReducer,
      admin: combineReducers({
        storage: storageReducer,
        classes: classesReducer,
        classEdit: classEditReducer,
        classEditStudents: classEditStudentsReducer,
        deleteConfirm: deleteConfirmReducer,
        actionConfirm: actionConfirmReducer,
        saveDialog: saveDialogReducer,
        admins: adminsReducer,
        adminEdit: adminEditReducer,
        students: studentsReducer,
        studentView: studentViewReducer
      })
    }));
    const engine = createEngine('vs45tgfr5678ikhy');
    const middleware = [thunk, storage.createMiddleware(engine)];
    const store = createStore(
      reducer,
      applyMiddleware(...middleware)
    );
    const load = storage.createLoader(engine);
    load(store);
    
    load(store)
      .then((newState) => console.log('STATE LOADED FROM INDEXED D:', newState))
      .catch(() => console.log('Failed to load previous state from local db!'));
    
    export default store;
    

    Fails on anything dispatched in the deleteConfirm:

    let initialState = {
        show: false,
        action: null,
        params: null,
        item: null
    };
    
    const deleteConfirmReducer = (state = initialState, action) => {
        let newState = {};
        let data = action.payload;
    
        switch (action.type) {
            case 'DELETE_CONFIRM_HIDE':
                newState = Object.assign({}, state);
                newState = {
                    show: false,
                    action: state.action,
                    params: state.params,
                    item: state.item
                };
                return newState;
    
            case 'DELETE_CONFIRM_UPDATE':
                newState = Object.assign({}, state);
                newState = {
                    show: true,
                    action: (!data.action) ? null : data.action,
                    params: (!data.params) ? null : data.params,
                    item: (!data.item) ? null : data.item
                };
                return newState;
    
            case 'DELETE_CONFIRM_RESET':
                newState = Object.assign({}, state);
                newState = {
                    show: false,
                    action: null,
                    params: null,
                    item: null
                };
                return newState;
    
            default:
                return state;
        }
    };
    
    export default deleteConfirmReducer;
    

    I cannot seem to find anything as to why.

    opened by SLYtiger16 0
  • Date being SAVEd is not fully the same data being LOADed.

    Date being SAVEd is not fully the same data being LOADed.

    Apologies if this is deemed a duplicate issue, but I felt my case was different enough from some of the other similar issues people were experiencing.

    I have a strange issue. I am using redux-storage to store to the device in react-native. In attempting to save some data in a large ImmutableJS object, I can create a reducer and query for the data on action REDUX_STORAGE_SAVE which looks like this:

    [ { id: 49, status: 'COMPLETE', status_set: '2016-10-20T16:37:51.516385Z' } ]

    The change to that data is the additions of the status_set property. After saving, if I continue to do things in the app, the state remains as reflected above.

    If I then reload the application, it loads data from storage storageEngine.load(store) I get:

    [ { id: 49, status: 'COMPLETE' } ]

    To further confuse, if I change the status in this example so on REDUX_STORAGE_SAVE it looks like:

    [ { id: 49, status: 'INCOMPLETE', status_set: '2016-10-20T16:37:51.516385Z' }

    After loading I get:

    [ { id: 49, status: 'INCOMPLETE' } ]

    So it is ok with updating a field, but not adding a new one? There are so many other places we add new fields, etc. and they all work.

    I am using the following redux-storage libraries:

    • redux-storage
    • redux-storage-decorator-debounce
    • redux-storage-engine-reactnativeasyncstorage
    • redux-storage-merger-immutablejs
    • redux-storage-decorator-filter I use a bunch of white/black listing here, this particular state tree is entirely in the white list.
    • redux-storage-decorator-migrate There are not migrations yet it should be noted.

    Really stuck on this and could use any insight into how I can further debug the issue!

    opened by gijoehosaphat 6
Releases(4.1.1)
  • 4.1.1(Aug 13, 2016)

  • 4.1.0(Aug 4, 2016)

  • 4.0.1(Aug 4, 2016)

  • 4.0.0(Mar 2, 2016)

    NEW FEATURE

    • Flexible state merger functions (issue #93 / PR #104)
    • If NODE_ENV != 'production', the save action issued by redux-storage contains a meta.origin with the action that trigged this save request. This is a pretty useful feature, if you want to track the origins of the save requests (issue #100 / PR #102)

    BREAKING CHANGES

    As we now support flexible state merger functions, ImmutableJS has completely been removed from this project! So if you're using redux-storage with ImmutableJS, you have to pass redux-storage-merger-immutablejs as second argument to storage.reducer!

    Old

    const reducer = storage.reducer(combineReducers(reducers));
    

    New

    $ npm install --save redux-storage-merger-immutablejs
    
    import immutableJsMerger from 'redux-storage-merger-immutablejs';
    
    const reducer = storage.reducer(combineReducers(reducers), immutableJsMerger);
    
    Source code(tar.gz)
    Source code(zip)
  • 3.0.1(Feb 29, 2016)

  • 3.0.0(Feb 10, 2016)

    Whoop! :tada: We've got time for issue #88 (PR #91) and redux-storage is now only the "management core" and all decorators and engines are distributed as own project/package on npm!

    Benefits of this transition range from less code you need to download and a more explicit dependency management to a more manageable codebase (multiple small projects instead of one big) and a more open plugin/extension culture. So go ahead and build more awesome decorators/engines! Just tag them properly and both engines and decorators can easily be browsed on npm :sunglasses:

    BREAKING CHANGES

    • All decorators have been removed and are now available as own npm packages:
      • decorator.filter => npm install --save redux-storage-decorator-filter
      • decorator.debounce => npm install --save redux-storage-decorator-debounce
      • decorator.immutablejs => npm install --save redux-storage-decorator-immutablejs
      • decorator.migrate => npm install --save redux-storage-decorator-migrate
    • All engines have been removed and are now available as own npm packge:
      • redux-storage/engine/reactNativeAsyncStorage => npm install --save redux-storage-engine-reactnativeasyncstorage
      • redux-storage/engine/localStorage => npm install --save redux-storage-engine-localstorage
      • redux-storage/engine/localStorageFakePromise => npm install --save redux-storage-engine-localstoragefakepromise
    Source code(tar.gz)
    Source code(zip)
  • 2.2.0(Feb 9, 2016)

  • 2.1.1(Feb 9, 2016)

  • 2.1.0(Feb 5, 2016)

  • 2.0.1(Feb 2, 2016)

  • 2.0.0(Jan 25, 2016)

  • 1.4.4(Jan 19, 2016)

  • 1.4.3(Jan 11, 2016)

  • 1.4.2(Jan 4, 2016)

  • 1.4.1(Dec 12, 2015)

  • 1.4.0(Dec 3, 2015)

  • 1.3.4(Dec 3, 2015)

  • 1.3.3(Dec 3, 2015)

  • 1.3.2(Dec 3, 2015)

  • 1.3.1(Dec 3, 2015)

  • 1.3.0(Dec 3, 2015)

Owner
Michael Contento
Michael Contento
The state manager ☄️

☄️ effector The state manager Table of Contents Introduction Effector follows five basic principles: Installation Documentation Packages Articles Comm

effector ☄️ 4k Jan 5, 2023
Predictable state container for JavaScript apps

Redux is a predictable state container for JavaScript apps. (Not to be confused with a WordPress framework – Redux Framework) It helps you write appli

Redux 59.1k Jan 9, 2023
COVID-19 Data: built with react and redux by using a public covid api

COVID-19 Data This is a React module capstone project. It is built with react and redux by using a public covid api. Screenshot Live Demo Live Link Vi

Tarikwa Tesfa 11 Jun 3, 2022
Official React bindings for Redux

React Redux Official React bindings for Redux. Performant and flexible. Installation Using Create React App The recommended way to start new apps with

Redux 22.5k Jan 3, 2023
redux higher order reducer + action to reduce actions under a single subscriber notification

redux-batched-actions Batching action creator and associated higher order reducer for redux that enables batching subscriber notifications for an arra

Tim Shelburne 1k Nov 21, 2022
store enhancer for https://github.com/reactjs/redux which allows batching subscribe notifications.

redux-batched-subscribe Store enhancer for redux which allows batching of subscribe notifications that occur as a result of dispatches. npm install --

Terry Appleby 500 Jan 3, 2023
Selector library for Redux

Reselect Simple “selector” library for Redux (and others) inspired by getters in NuclearJS, subscriptions in re-frame and this proposal from speedskat

Redux 18.8k Dec 27, 2022
Dead simple + opinionated toolkit for building redux/react applications

Simple opinionated toolkit for building applications using React, Redux, and Immutable.js You're early! There is sparse documentation, no tests, and i

shasta (archive) 517 Sep 29, 2022
A performant, scalable and pluggable approach to instrumenting your React application.

react-i13n react-i13n provides a performant, scalable and pluggable approach to instrumenting your React application. Typically, you have to manually

Yahoo 369 Dec 25, 2022
Declarative data-fetching and caching framework for REST APIs with React

resourcerer resourcerer is a library for declaratively fetching and caching your application's data. Its powerful useResources React hook or withResou

Noah Grant 75 Jun 24, 2022
⚡️The Fullstack React Framework — built on Next.js

⚡️The Fullstack React Framework — built on Next.js

⚡️Blitz 12.5k Jan 9, 2023
⚡️The Fullstack React Framework — built on Next.js — Inspired by Ruby on Rails

⚡️The Fullstack React Framework — built on Next.js — Inspired by Ruby on Rails

⚡️Blitz 9.4k Oct 12, 2021
A game of Candy Crush in React where you can save game state

Candy Crush In React This project is in support of the video tutorials found here for Part 1 and Part 2 coming soon. In Part 1 we creact the ReactJS g

Ania Kubow 20 Oct 31, 2022
Manage the state of your React app with ease

@spyna/react-store React app state management that uses a storage Demo https://spyna.github.io/react-store/ Install npm install --save @spyna/react-st

Lorenzo Spinelli 46 Jan 19, 2021
React Redux Multi-Step Signup Form. Created with React, Redux Toolkit, and SASS. Plus React Lazy Load for Component loading.

React Redux Multi-Step Signup Form. Created with React, Redux Toolkit, and SASS. Plus React Lazy Load for Component loading.

Rishi Singh Bhachu 16 Nov 9, 2022
Spaceflix is a pixel-perfect clone of Netflix. Browse and watch trailers, create individualized profiles, and save movies to your personal list for later viewing.

Spaceflix Visit the Live Site here Spaceflix is a space-themed, pixel-perfect clone of Netflix. Like the real thing, Spaceflix allows users to stream

Ezra Hecker 58 Nov 22, 2022
React Native Typescript Template with scalable design and cutting edge technologies like CodePush, Sentry and other libraries pre-configured to save your time.

A React Native Template/Boilerplate containing the best practices and scalable design with cutting edge technologies like CodePush/Sentry and all other neccessary libraries pre-configured and basic helper functions and components to help you save your time and make your App super fast.

KASHAN HAIDER 23 Dec 1, 2022
Save mouse positions and visit them using shortcut keys

Bookmark mouse position Save mouse positions using a shortcut key and quickly traverse to them using another shortcut key. bookmark-mouse-positions.1.

Nishan 5 Oct 27, 2022
A weather app done with React. Allows you to make a search for the current weather by simply typing "common knowledge" cities and save them to favourites on local storage.

Simpliest Weather React-App A weather app done with React. Allows you to make a search for the current weather by simply typing "common knowledge" cit

Larry Noriega 3 Aug 24, 2022
Paperfreeform - A Free Form Builder to save trees and create beautiful forms

PaperFreeForm PaperFreeForm is a Free Form Builder to save trees and create beau

Zaid Mukaddam 5 Feb 24, 2022