rt2zz / redux-persist Goto Github PK
View Code? Open in Web Editor NEWpersist and rehydrate a redux store
License: MIT License
persist and rehydrate a redux store
License: MIT License
I dont necessarily need to handle both in and out. So having to add a dummy pass-through handler now, feels a bit wrong.
I am having an issue where a couple of actions does not seems to be caught by this lib, so they are not being persisted. This is a gist of what I'm doing, where it doesn't work for me:
dispatch(uploadBegun(item.id));
fileReader(file).then(reader => {
dispatch(createEntity( ... )).then(res => {
dispatch(setItemDetail( item.id, ... ));
dispatch(uploadDone( item.id ));
});
});
I've tried to add a transformer which logs what comes in to redux-persist, and it shows the wrong data coming after the setItemDetail
and uploadDone
actions have been dispatched. Neither are registered.
Could this be a bug triggered by dispatching two actions "simultaneously"?
Because sometimes it's easier to write whitelist: ['user'] instead of blacklist: [..list 10 reducers and remember to list new ones as well
]... Is this something you've been considering already in the past?
I playing around with redux-persist and redux-persist-immutable to store my app state.
The state is a combinedReducer object with immutable data structure down from the second level in the state tree.
persisting the individual immutable subtrees works very nice with the redux-persist-immutable transform. Unfortunately during rehydration the immutable is correctly restored from local storage but the merge into the store object goes wrong.
The problem seems to be the for...in
construct in autoRehydrate.js lines 56,57.
for...in
iterates over all properties along the prototype chain and in the case of Immutable.js objects the final object that is merged contains all prototype props in the main level (for...in MDN).
Maybe a quick fix could look something like
...
for (var subkey in reducedState[key]) {
if (reducedState[key].hasOwnProperty(subkey)) subState[subkey] = reducedState[key][subkey]
}
for (var datakey in data) {
if (data.hasOwnProperty(datakey)) subState[datakey] = data[datakey]
}
subState.__proto__ = data.__proto__;
autoReducedState[key] = subState
...
I am seeing this error in console and most probably that's happening on the node server side (isomorphic app). Is there a way to handle this?
rehydrateAction
and completeAction
persistor.rehydrate
accept "serialized" payload or should deserialization be a responsbility of the caller?skipRestore: true
let {persistStore, autoRehydrate} = createPersistScheme(config)
This is what I get when rehydrating an Immutable map:
iterable.length has been deprecated, use iterable.size or iterable.count() *snip*
at Map.Object.defineProperty.get
at *snip* // in lodash.baseProperty
at isArrayLike
at isArrayLikeObject
at isArguments
at Object.isPlainObject [as default]
at *snip* // in redux-persist.createRehydrationReducer
at computeNextEntry
at recomputeStates
at *snip* // in redux.liftReducerWith
The line of interest. It appears that lodash.isplainobject
involves checking whether that object has a length
property or not, and Immutable doesn't like that. There's a very similar resolved issue in redux-storage
. Here's their fix.
Breaking changes
autoRehydrate
no longer implement an action buffer. It was too automagical and caused some bugs with dispatch return values. Updgrade path: implement redux-action-bufferOther changes of note
createPersistor
method that handles subscribing to the store and persisting to the storage engine.persistStore
now simply calls getStoredState
and createPersistor
getStoredState
now support promiseskeys
-> getAllKeys
createTransform(inbound, outbound, {whitelist, blacklist})
methodtodo
Because typeof [] == 'object' in our favorite language, the reducer in autoRehydrate will activate the shallow merge behavior for arrays and turn them into objects. I'm currently working around this with a custom autoRehydrate, but it would be nice if this were handled better.
Open question: should arrays be shallow-merged, or slurped in without modification? I'd say the latter, both because it makes more sense for my application and because I don't think arrays can be sanely merged.
Be careful with localStorage
! The data might get corrupted or something, so try
/catch
is a good idea.
Worse, iOS in private mode will throw on every .setItem
or .getItem
call.
As per the "Custom Rehydration" section in recipies.md, I implemented a case REHYDRATE
statement in my reducer.
case REHYDRATE:
const { key } = action // key = undefined !!!
if (key === 'newAppointmentForm') { // key === 'forms.newAppointmentForm' ?
const startedMoment = moment(action.payload.startedMoment)
return Object.assign({}, state, { startedMoment })
}
However, when the action fires during the rehydration process, the action has no key
attribute attached.
My alternate method (which seems to work) is to simply pull out the relevant part of the state tree from action.payload
, and implement my custom rehydration logic there:
case REHYDRATE:
const startedMoment = moment(action.payload.forms.newAppointmentForm.startedMoment)
return Object.assign({}, state, { startedMoment })
Could you confirm that this is the "new" way of doing things, and that the docs are just out-of-sync with the API?
Thanks!
EDIT: found the problem.
My package.json uses ^1.5.0, and downloads 1.5.2, which breaks changes.
Hello,
I am having a problem with redux-persist, but I believe it has something to do with my environment, not specifically this package. However since the error clearly happens during the use of this package, I thought you might have a hint to solve my problem!
Here is the issue: https://stackoverflow.com/questions/35296078/localstorage-suddenly-broken
Thanks.
Hey guys, I'm trying to persist a Javascript Date object in the redux store, but it seems to be serializing into a string automatically, without being deserialized upon rehydration. Right now I can handle it with a transform (although it's a little messy), I feel like this should be default behavior, what do you guys think?
At the very least we could put a warning when persisting and then rehydrating gives you back a different object.
I'm having a problem regarding the new version of redux-persist that may be very specific to the project I'm working on right now, but, nevertheless, I'll describe it here.
I have a logout action that resets all reducers to the initial state and I'm also using autoRehydrate to load the previous state stored in AsyncStorage (it's a react native app). The issue happens when I open the app, get the state rehydrated and I try to logout immediately after that. The state is never persisted.
By calling "persistStore", the "createPersistor" function is invoked and a new persistor is created with its lastState set to the initial state. The persistor is then paused, which is resumed only after rehydration. That means the "lastState" on the persistor is still the initial state, even after rehydration. When I dispatch my logout action, the new state is compared to the "lastState" and as both are the same, nothing gets persisted in AsyncStorage. If I reload the app the state is still the same before I logged out.
I don't know if this is the intended behaviour or if it's a bug. Is there any reason why the persistor needs to get paused during rehydration?
My app crashes on launch as soon as I add autoRehydrate()
to my createStore
-function. It can be launched when there is no data to rehydrate, but as soon as I persist my first store and reload the app, it crashes. I tried removing thunk
-middleware, but that doesn't help.
"react-native": "^0.21.0",
"react-redux": "^4.4.0",
"redux": "^3.3.1",
"redux-persist": "^2.0.1",
"redux-thunk": "^2.0.1"
const store = createStore(
reducer,
{},
compose(
autoRehydrate(),
applyMiddleware(thunk),
)
);
2016-03-14 00:12:02.720 Bayern2[99566:9307470] *** Assertion failure in __33-[RCTUIManager setFrame:forView:]_block_invoke(), [...]/node_modules/react-native/React/Modules/RCTUIManager.m:379
2016-03-14 00:12:02.721 Bayern2[99566:9307470] *** Terminating app due to uncaught exception 'NSInternalInconsistencyException', reason: 'Could not locate root view with tag #46'
*** First throw call stack:
(
0 CoreFoundation 0x0000000104abce65 __exceptionPreprocess + 165
1 libobjc.A.dylib 0x0000000103cc0deb objc_exception_throw + 48
2 CoreFoundation 0x0000000104abccca +[NSException raise:format:arguments:] + 106
3 Foundation 0x000000010390d5a2 -[NSAssertionHandler handleFailureInFunction:file:lineNumber:description:] + 169
4 AppName 0x000000010360e458 __33-[RCTUIManager setFrame:forView:]_block_invoke + 392
5 libdispatch.dylib 0x000000010803fe5d _dispatch_call_block_and_release + 12
6 libdispatch.dylib 0x000000010806049b _dispatch_client_callout + 8
7 libdispatch.dylib 0x00000001080468ec _dispatch_queue_drain + 2215
8 libdispatch.dylib 0x0000000108045e0d _dispatch_queue_invoke + 601
9 libdispatch.dylib 0x0000000108048a56 _dispatch_root_queue_drain + 1420
10 libdispatch.dylib 0x00000001080484c5 _dispatch_worker_thread3 + 111
11 libsystem_pthread.dylib 0x000000010839868f _pthread_wqthread + 1129
12 libsystem_pthread.dylib 0x0000000108396365 start_wqthread + 13
)
libc++abi.dylib: terminating with uncaught exception of type NSException
Does this commit indicate that you were able to get these working together or just that it wasn't an issue worth investing in at that point? 340ff7a#diff-04c6e90faac2675aa89e2176d2eec7d8L87
It seems like setting debounce
for persistStore
will discard state updates that falls outside the interval.
I will see to get a minimal working example asap, but for now I've registered this issue.
Hi,
Any chance on support react-native 0.23.x? I'd love to use this as I have not found a clean way to restore long-life app state.
Redux Persist currently emits several rehydration actions: one for every reducer. It was designed this way because it directly reflects the way redux persist works under the hood, on a per reducer basis. However we could just as easily merge every persisted value into one single 'initial state' object and fire a single REHYDRATE
action.
Pros:
REHYDRATE_COMPLETE
actionCons:
Thoughts?
Hi,
how can I use your tool with redux-thunk? I have the lines
const createStoreWithMiddleware = applyMiddleware(thunk)(createStore); const reducer = combineReducers(reducers); const store = createStoreWithMiddleware(reducer);
How would I integrate redux-persist into that? Thanks a lot.
Hi, my store is
{userStore: {name: '', duty: '', userObj: {"first":xxx, "second": xxx}}}
When restore from the AsyncStorage, i found the the value of key userObj is String, not Object, how to fix it?
I'm trying to follow the basic setup to add this to https://github.com/davezuko/react-redux-starter-kit, but I'm getting this error:
persistStore.js line 37:
var lastState = store.getState();
ERROR: store.getState is not a function
Setup code:
const store = compose(autoRehydrate())(createStoreWithMiddleware(createStore)(
rootReducer, initialState
));
persistStore(store)
I'm (attempting) to debug this and will hopefully self-close - just opening an issue for the future if/when someone else sees this issue.
Want to integrate redux-persist with this https://github.com/multunus/react-native-boilerplate. Maybe a recipe for immutable state
I've been looking into different options for a persistence layer to work with a server-side redux app based on this full-stack-redux-tutorial by Tero Parviainen.
After looking into RethinkDB and Redis as options to back up the server side store, I started thinking that all I need to do is to write the current state or a log of the actions to disk so that when the server needs a restart I don't lose the store. Likewise, hydration functionally will be necessary after a restart. Other than that, my server side store can act as a full on substitute for a database. I don't really need anything except to protect against losing the store. So a few Google searches later and I'm here.
At least some of the readme docs suggests this package is for the client side. Would this package also be a substitute for a database on the back end? It sounds like the right idea.
Let's say I wanted to store booleans, or objects.
AsyncStorage gives an error if it isn't a string. Is there a conversion? Or is it just not allowed?
Currently one can specify a white or blacklist of actions which should be persisted. I would like to specify a function instead which is passed the action and determine whether a rehydrate should be performed or not. If you agree I can submit a PR.
This is probably a stupid question, but is the store persisted constantly? Or should I call persistStore
explicit after a certain action is done? For instance, I load my store on a fresh application so the user
will be empty. After logging in I would like to persist the store which now contains user data such as a session token.
How could I achieve that? In my redux
action or reducer I always have access to a part of the state, never the complete store? My goal is that after logging in and reloading the app, the store is rehydrated with the previous session token, thus the user is logged in. Right now I achieved that with AsyncStorage
but the redux-persist
API is much more transparent in a way that I don't need special callbacks throughout my actions, I can just inspect the store.
React Native 0.16 upgraded to Babel 6, which chokes on redux-persist
's .babelrc
file (I think because it uses the stage
field). You can see how react-redux
dealt with that change, basically it looks like you just don't want to ship a .babelrc
as part of the published package. I think that's the only change needed, let me know if you want any more diagnostic info.
REHYDRATE
action is emittedREHYDRATE_COMPLETE
has been removedrehydrateAction
configuration optionHere is my application.jsx right now:
'use strict';
import 'babel-polyfill';
import React from 'react';
import ReactDOM from 'react-dom';
import { Router, Route, IndexRoute } from 'react-router';
import createHistory from 'history/lib/createHashHistory';
import { Provider } from 'react-redux';
import { compose, createStore, combineReducers, applyMiddleware } from 'redux';
import createLogger from 'redux-logger';
import { persistStore, autoRehydrate } from 'redux-persist';
import thunk from 'redux-thunk';
import { syncHistory, routeReducer } from 'redux-simple-router';
import reducers from './reducers';
const history = createHistory();
const logger = createLogger();
const middleware = syncHistory(history);
const reducer = combineReducers(Object.assign({}, reducers, {
routing: routeReducer
}));
const store = compose(autoRehydrate(), applyMiddleware(
middleware,
thunk,
logger
))(createStore)(reducer);
persistStore(store);
import App from './containers/App';
import Home from './views/Home';
import Login from './views/Login';
import Register from './views/Register';
import About from './views/About';
import './style.css';
ReactDOM.render(
<Provider store={store}>
<div>
<Router history={history}>
<Route path="/" component={App}>
<IndexRoute component={Home} />
<Route path="login" component={Login} />
<Route path="register" component={Register} />
<Route path="about" component={About} />
</Route>
</Router>
</div>
</Provider>,
document.getElementById('app')
);
Any help would be appreciated! I just tried out the simple solution and works like a charm.
I'm having trouble setting up redux-persist. I keep getting an error - _this.store.getState is not a function
I have no idea why it's not working, I also found that their weren't any examples! If I get this running I'll try put up an example for other users.
This is my configureStore.js file
import {AsyncStorage,} from 'react-native';
import { createStore, applyMiddleware, compose, combineReducers, } from 'redux';
import reduxThunkMiddleware from 'redux-thunk';
import Reactotron from 'reactotron';
import * as reducers from './modules';
import devTools from 'remote-redux-devtools';
import {persistStore, autoRehydrate} from 'redux-persist'
Reactotron.connect({
enabled: __DEV__,
});
const enhancer = compose(
autoRehydrate(),
applyMiddleware(
reduxThunkMiddleware,
Reactotron.reduxMiddleware,
),
devTools()
);
export default function configureStore(initialState) {
const store = createStore(
combineReducers({
...reducers,
}),
initialState,
enhancer,
);
Reactotron.addReduxStore(store, {storage: AsyncStorage});
return store;
}
And here is where I'm passing the store down to the <provider>
component
import createStore from './redux/configureStore';
import {persistStore} from 'redux-persist'
const store = persistStore(createStore(), {storage: AsyncStorage});
const RouterWithRedux = connect()(Router);
const Kernel = () => (
<Provider store={store}>
Also a question I have:
Is it possible for me to only persist an array of reducers? I've got about 10 reducers, and I'd only like to persist 2 or 3 of them to AsyncStorage
?
Has there been any thoughts on using compression before storing to local storage? Was playing around with this library, http://pieroxy.net/blog/pages/lz-string/index.html, and it looks like you can get a significant storage savings.
On React Native, what about integration with https://github.com/realm/realm-js, using it as a backend storage? Redux Persist currently uses AsyncStorage as storage, is Realm a natural fit here instead?
Reference: realm/realm-js#141 (comment)
Hey! First of all, great work on the lib, I am currently using it for a personal project https://github.com/Tiagojdferreira/ryuutama and I am loving it.
Recently I have added taobaofed/react-web and realised that both libraries don't seem to work together. You can find the original issue here taofed/react-web#94
I will try to find more details about the problem, but you can see that commenting out redux-persist makes the app work again
Tiagojdferreira/ryuutama@891ab33
Hello.
I've added store enhancer as the third argument to createStore()
let middleware = applyMiddleware(thunk, promiseMiddleware(), routerMiddleware(history))
const store = createStore(rootReducer, initialState, compose(
autoRehydrate(),
middleware
))
And, after doing so, dispatch(action)
calls began to return undefined
.
Following the official Redux docs, dispatch()
returns dispatched action (or return value from the middleware). It would be useful if store enhancer wouldn't break default behavior.
skipDispatch
is listed as an option in the Readme, but it's not in the code anywhere. Not sure if this was removed?
Also I'm wondering if the plan is still to not dispatch the REHYDRATE actions when v2.0 lands? Alternately, is there any recommended pattern for delaying the loading/rendering of the rest of an app until persist/COMPLETE
is fired?
Since this lib is backend-agnostic, it probably shouldn't implement any localStorage event listening, but a recipe would be nice (e.g. the usual authentication scenario, where a user logs in/out in one tab, and the other tab gets updated accordingly). How would you go about syncing the state across tabs, when using redux-persist?
I have some arrays in my state that I don't need at app start right away. I'd rather load them when I first need to display them. Does redux-persist support that?
Hi, I'm using the latest version and I can't figure out how to persist to local storage the initial state I pass to createStore. It looks like redux-persist starts to sync state with the local storage as soon as I fire up an actions.
I'm after a way to store some initial data that my server provides on the window object (I'm doing server side rendering).
Thanks!
It would be helpful if the transforms' "in" and "out" handlers receive the current key as an argument. That would enable per-key transform logic.
I still looking into it, but it would be great to achieve. Now the reducers are initiated twice: the first one with the initial value, and the second - with the rehydrated one. I tried to find some solutions, but all of them seems to be antipattern, except of this. Actually, this is the purpose of the store's initialState to pass the rehydrating state from server or localStorage.
What do you think if we get the data from the localStorage before creating the store?
It seems that the provision for a custom actionCreator has been removed at some point since v1.5.3 and v2.0.1. Is there an alternative recommendation for handing the data to be rehydrated to an action creator upon rehydration?
I noticed that purge is a function of redux-persist store, but how would I invoke it in a typical UI button, where I don't get access to store, only dispatch. I see this as a potential solution: http://stackoverflow.com/questions/33643290/how-do-i-get-a-hold-of-the-store-dispatch-in-react-router-onenter
would you do that, despite comments saying you shouldn't?
I'm getting this error while building nw.js chromium app with this index.js
webpack:///./~/redux-persist/lib/persistStore.js?:49 Uncaught ReferenceError: setImmediate is not defined
I thought setImmediate was not supported natively in most of browsers.
import React from 'react';
import { render } from 'react-dom';
import { Provider } from 'react-redux';
import { Router } from 'react-router';
import routes from './routes';
import configureStore from './store/configureStore';
import './app.css';
import {persistStore, autoRehydrate} from 'redux-persist'
const store = configureStore();
persistStore(store);
render(
<Provider store={store}>
<Router>
{routes}
</Router>
</Provider>,
document.getElementById('root')
);
If a reducer for a sub state returns a new but identical state object, autoRehydrate detects this as a change and skips rehydrating that sub state.
... because of missing return
in asyncLocalStorage.js. Submitting a pull request
A declarative, efficient, and flexible JavaScript library for building user interfaces.
๐ Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. ๐๐๐
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google โค๏ธ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.