I've been trying to use redux-perist to save my redux-state to AsyncStorage. Although I keep getting an error:
_this.store.getState is not a function
I'm not sure why this is happening?
Here is my setup:
configureStore.js:
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;
}
App.js:
Here is where I connect my store, to my <provider>:
import React from 'react';
import {AsyncStorage} from 'react-native';
import { Provider, connect } from 'react-redux';
import { Router } from 'react-native-router-flux';
import routes from '#routes/app';
import createStore from './redux/create'; // Returns store object from the above configureStore.js!
import {persistStore} from 'redux-persist'
const RouterWithRedux = connect()(Router);
const store = persistStore(createStore(), {storage: AsyncStorage}); // Not working??
const Kernel = () => (
<Provider store={store}>
<RouterWithRedux scenes={routes} />
</Provider>
);
export default Kernel;
const RouterWithRedux = connect()(Router);
const store = createStore();
const persistor = persistStore(store, {storage: AsyncStorage}); // Not working??
const Kernel = () => (
<Provider store={store} persistor={persistor}>
<RouterWithRedux scenes={routes} />
</Provider>
);
The problem was I had to pass down a persistor field as well as the store field.
After adding in the persistor field, my store was being persisted into AsyncStorage
EDIT:
This worked at the time - It has occured to me that this not the correct solution to the problem. But I'm still getting responses that it still works, if someone could provide another answer for everyone else, that'd be great.
Related
I'm getting the error on the header when I try to add the store into my app
this is my store.js code
import { createStore, applyMiddleware } from 'redux';
import { persistStore } from 'redux-persist';
import logger from 'redux-logger';
import createSagaMiddleware from 'redux-saga';
import { composeWithDevTools } from 'redux-devtools-extension';
import rootReducer from './root-reducer';
import rootSaga from './root-saga';
const sagaMiddleware = createSagaMiddleware();
const middlewares = [sagaMiddleware];
//if (process.env.NODE_ENV === 'development') {
middlewares.push(logger);
//}
sagaMiddleware.run(rootSaga);
const configureStore = () => {
const store = createStore(rootReducer, composeWithDevTools(applyMiddleware(...middlewares)));
const persistor = persistStore(store);
return { persistor, store };
};
export default configureStore;
This is my index.js
import React from 'react';
import ReactDOM from 'react-dom';
import { BrowserRouter as Router } from "react-router-dom";
import { Provider } from 'react-redux';
import { PersistGate } from 'redux-persist/integration/react';
import App from './App';
import configureStore from './redux/store';
ReactDOM.render(
<React.StrictMode>
<Provider store={configureStore}>
<Router>
<PersistGate persistor={configureStore}>
<App />
</PersistGate>
</Router>
</Provider>
</React.StrictMode>,
document.getElementById('root')
);
Could you please help identify the issue here please? Thanks in advance
Running saga should be after creating the store like that:
...
const configureStore = () => {
const store = createStore(rootReducer, composeWithDevTools(applyMiddleware(...middlewares)));
sagaMiddleware.run(rootSaga);
const persistor = persistStore(store);
return { persistor, store };
};
Another point here, regarding TypeError: store.getState is not a function: you're returning function, not a result of the function: so typically it should be like this:
const configureStore = () => {
const store = createStore(
rootReducer,
composeWithDevTools(applyMiddleware(...middlewares))
);
const persistor = persistStore(store);
sagaMiddleware.run(rootSaga);
return { persistor, store };
};
export default configureStore();
The persistor isn't returned here, but the application works.
There is an instruction how to add redux-persist https://github.com/rt2zz/redux-persist#basic-usage, but then you need to get separately store and persistor like:
import configureStore from "./store";
ReactDOM.render(
<React.StrictMode>
<Provider store={configureStore.store}>
<Router>
<App />
</Router>
</Provider>
</React.StrictMode>,
document.getElementById("root")
);```
Getting an Error: Before running a Saga, you must mount the Saga middleware on the Store using the applyMiddleware
Error explanation
Your error says you are trying to execute a saga too soon
Explaining you to run your middleware before.
Therefore your solution is to execute `saggaMiddleware.run() after creating your store.
What happened based on your code
You were trying to execute sagaMiddleware.run() method before mounting your store at the third line with composeWithDevTools(applyMiddleware(...middlewares))
Solution
Here is a solution respecting your line declarations order + added one more line before return to execute the runSagaMiddleware
const runSagaMiddleware = () => sagaMiddleware.run(rootSaga);
const configureStore = () => {
const store = createStore(rootReducer, composeWithDevTools(applyMiddleware(...middlewares)));
const persistor = persistStore(store);
runSagaMiddleware();
return { persistor, store };
};
I'm using react-native with redux-saga but this error happens when emulator acting
error: attempt to invoke virtual method on a null object reference
i think this code is problem
(App.js)
import React from 'react';
import Store from './store/configureStore'
import {Provider} from 'react-redux';
import {App} from './src/index';
const Root = () => {
return (
<Provider store={Store()}>
<App />
</Provider>
);
};
export default Root;
(configure/configure.js)
import { applyMiddleware, createStore, compose } from 'redux';
import createSagaMiddleware from 'redux-saga';
import { composeWithDevTools } from 'redux-devtools-extension';
import reducer from '../reducers';
import rootSaga from '../sagas';
const Store = () => {
const sagaMiddleware = createSagaMiddleware();
const middlewares = [sagaMiddleware];
const enhancer = process.env.NODE_ENV === 'production'
? compose(applyMiddleware(...middlewares))
: composeWithDevTools(
applyMiddleware(...middlewares),
);
const store = createStore(reducer, enhancer);
store.sagaTask = sagaMiddleware.run(rootSaga);
return store;
};
export default Store;
i think error occure is beacuse redux-saga stroe.. how can i fix my code?
I'm trying to build react app with typescript using redux for state management but I'm getting this error on the app component.
-app.tsx
import React from 'react';
import { Provider } from 'react-redux';
//import { Router } from "react-router";
import store from './redux/store';
import './App.css';
function App() {
return (
<Provider store={store}>
</Provider>
);
}
export default App;
-Store.tsx
import { createStore, applyMiddleware, compose } from 'redux';
import { createLogger } from 'redux-logger';
import thunk from 'redux-thunk';
import rootReducer from './reducers';
const loggerMiddleware = createLogger()
// For redux DevTool
declare global {
interface Window {
__REDUX_DEVTOOLS_EXTENSION_COMPOSE__?: typeof compose;
}
}
const composeEnhancers = window.__REDUX_DEVTOOLS_EXTENSION_COMPOSE__ || compose;
const enhancer = composeEnhancers(
applyMiddleware(thunk, loggerMiddleware)
);
const initialState = {};
const store = createStore(rootReducer, initialState, enhancer);
export default store;
I tried to inject the store in the index but i have the same error with.. Any idea where the issues came from??
That is because TypeScript is unable to infer the typings of your redux store state.
If you have not created the types, you will need to define the types of your store using interfaces or type aliases:
export interface RootState {
// add required properties from your store
}
On your app.tsx,
import { Store as ReduxStore } from 'redux';
// other imports
interface AppProps {
store: ReduxStore<RootState>;
}
const App: React.FC<AppProps> = ({ store }) => (
<Provider store={store}>
<App onLoad={onLoad} />
</Provider>
);
I made a single page application using React.js with a login page and perfil page. All works well but recently I noticed when refresh my page, all states are empty. Please someone can say me how to fix that issue, I mean what library import and where add it
my index.js
import React from 'react';
import ReactDOM from 'react-dom';
import './index.css';
import App from './components/App.jsx';
import * as serviceWorker from './serviceWorker';
ReactDOM.render(<App />, document.getElementById('root'));
serviceWorker.unregister();
this is my App.jsx
import React from 'react';
import '../App.css';
import AppRoutes from './AppRoutes';
import { Provider } from "react-redux";
import store from '../redux/store'
store.dispatch(getTallerList())
const App = () => (
<Provider store={store}>
<AppRoutes />
</Provider> )
export default App;
and my store.js
import { applyMiddleware, combineReducers, createStore } from 'redux'
import { ADD_TO_CART, GET_COURSE_LIST, USUARIO_LOGIN } from './action'
import { composeWithDevTools } from 'redux-devtools-extension'
import { persistStore, persistReducer } from 'redux-persist'
import thunk from 'redux-thunk'
const initialCart = {
cart:[]
}
const initialCourses ={
courses:[]
}
const initialUser ={
user:{}
}
const cartReducer = ( state = initialCart,action) => {
if(action.type===ADD_TO_CART)
{
if(state.cart.find(c=>c===action.id))
{
return state
}
return{
...state,
cart: state.cart.concat(action.id),
}
}
return state
}
const coursesReducer = (state=initialCourses, action) =>{
console.log(action)
if(action.type === GET_COURSE_LIST){
return {
...state,
courses: action.courses
}
}
return state
}
const userReducer = (state=initialUser, action)=>{
console.log(action)
if(action.type === USER_LOGIN){
return {
...state,
user: action.user
}
}
return state
}
export default createStore(combineReducers({cartReducer, coursesReducer, userReducer}), composeWithDevTools(applyMiddleware(thunk)))
Try to store value in local storage and at the time of page load get value from local storage. If you have some more values you should use redux for data storage.
It's not an issue, it's the way it works. When you refresh the entire app builds once again from the scratch.
But to persist the store upon refresh you can use these redux middlewares -
redux-persist or
redux-storage
Use this configuration as you are using redux-persist. This is my configuration, just change the main app, reducers, and actions according to your need.
import React from 'react';
import ReactDOM from 'react-dom';
import MyApp from './MyApp';
import {Provider} from 'react-redux';
import {applyMiddleware, createStore} from "redux";
import allReducers from './reducers/index';
import {persistReducer, persistStore} from 'redux-persist';
import {PersistGate} from 'redux-persist/integration/react';
import storage from 'redux-persist/lib/storage';
import thunk from "redux-thunk";
const persistConfig = {
key: 'root',
storage,
};
const persistedReducer = persistReducer(persistConfig, allReducers);
let store = createStore(persistedReducer, applyMiddleware(thunk));
let persistor = persistStore(store);
ReactDOM.render(<Provider store={store}>
<PersistGate loading={null} persistor={persistor}>
<MyApp/>
</PersistGate>
</Provider>, document.getElementById('root'));
Updated : you can do like this
import {combineReducers} from "redux";
import Users from './load-user';
const allReducers = combineReducers({
users: Users,
})
export default allReducers
I am learning redux and came up with an example using a webservice that
returns data. Everything is working. However I configured the redux developer tools
below.
I got an error saying my store is assigned a value but never used and when I go into
my dev tools, I am not able to see my state data. Am i doing something wrong?
import React from 'react';
import ReactDOM from 'react-dom';
import { BrowserRouter as Router, Route } from 'react-router-dom';
import promise from 'redux-promise';
import { Provider } from 'react-redux';
import { createStore, applyMiddleware, compose } from 'redux';
import reducers from './reducers';
import ProductsIndex from './components/products_index';
const createStoreWithMiddleware = applyMiddleware(promise)(createStore);
const composeEnhancers = window.__REDUX_DEVTOOLS_EXTENSION_COMPOSE__ || compose;
const store = createStore(
reducers,
composeEnhancers(applyMiddleware())
);
ReactDOM.render(
<Provider store={createStoreWithMiddleware(reducers)}>
<Router>
<div>
<Route path="/" component={ProductsIndex} />
</div>
</Router>
</Provider>
, document.querySelector('#root'));
Error: Line 14:7: 'store' is assigned a value but never used no-unused-vars
Here is what I usually do.
configureStore.js
import { createStore, applyMiddleware, compose } from "redux";
import thunk from "redux-thunk";
import logger from "redux-logger";
import createRootReducer from "../reducers";
const middleware = window.ENV.environment === "local" ? [thunk, logger] : [thunk];
const composEnhancers = window.__REDUX_DEVTOOLS_EXTENSION_COMPOSE__ || compose;
const enhancer = composEnhancers(applyMiddleware(...middleware));
const configureStore = (initialState) => {
return createStore(createRootReducer(), initialState, enhancer);
};
export default configureStore;
App.js
import configureStore from "./configureStore";
const store = configureStore();
const App = () => {
return (
<Provider store={store}>
<BrowserRouter basename={process.env.PUBLIC_URL}>
// ...
</BrowserRouter>
</Provider>
);
};