Redux-persist does not work with Redux-Toolkit - javascript

The app works fine The only thing is that redux persist is not working as it should.Persist doest not persist anything,it does not give any errors in the console(in VSC or in Chrome) so I have zero information about where it is failing.Any ideas? thanks for your time and sorry for my bad english
This is the App.js
import FuseAuthorization from '#fuse/core/FuseAuthorization';
import FuseLayout from '#fuse/core/FuseLayout';
import FuseTheme from '#fuse/core/FuseTheme';
import history from '#history';
import { createGenerateClassName, jssPreset, StylesProvider } from '#material-ui/core/styles';
import { MuiPickersUtilsProvider } from '#material-ui/pickers';
import { create } from 'jss';
import jssExtend from 'jss-plugin-extend';
import rtl from 'jss-rtl';
import Provider from 'react-redux/es/components/Provider';
import { Router } from 'react-router-dom';
import { SnackbarProvider } from 'notistack';
import DateFnsUtils from '#date-io/date-fns';
import AppContext from './AppContext';
import { Auth } from './auth';
import routes from './fuse-configs/routesConfig';
import {store persistor} from './store';
import { PersistGate } from 'redux-persist/integration/react';
import { persistStore } from 'redux-persist';
const jss = create({
...jssPreset(),
plugins: [...jssPreset().plugins, jssExtend(), rtl()],
insertionPoint: document.getElementById('jss-insertion-point')
});
const generateClassName = createGenerateClassName({ disableGlobal: true });
const App = () => {
return (
<AppContext.Provider
value={{
routes
}}
>
<StylesProvider jss={jss} generateClassName={generateClassName}>
<Provider store={store}>
<PersistGate persistor={persistor}>
<MuiPickersUtilsProvider utils={DateFnsUtils}>
<Auth>
<Router history={history}>
<FuseAuthorization>
<FuseTheme>
<SnackbarProvider
maxSnack={5}
anchorOrigin={{
vertical: 'bottom',
horizontal: 'right'
}}
classes={{
containerRoot: 'bottom-0 right-0 mb-52 md:mb-68 mr-8 lg:mr-80 z-99'
}}
>
<FuseLayout />
</SnackbarProvider>
</FuseTheme>
</FuseAuthorization>
</Router>
</Auth>
</MuiPickersUtilsProvider>
</PersistGate>
</Provider>
</StylesProvider>
</AppContext.Provider>
);
};
This is where the store is created:
import { configureStore } from '#reduxjs/toolkit';
import createReducer from './rootReducer';
import storage from 'redux-persist/lib/storage';
import { persistReducer } from 'redux-persist';
if (process.env.NODE_ENV === 'development' && module.hot) {
module.hot.accept('./rootReducer', () => {
const newRootReducer = require('./rootReducer').default;
store.replaceReducer(newRootReducer.createReducer());
});
}
const middlewares = [];
if (process.env.NODE_ENV === 'development') {
const { createLogger } = require(`redux-logger`);
const logger = createLogger({ collapsed: (getState, action, logEntry) => !logEntry.error });
middlewares.push(logger);
}
const persistConfig = {
key: 'root',
storage
};
const persistedReducer = persistReducer(persistConfig, createReducer());
export const store = configureStore({
reducer: persistedReducer,
middleware: getDefaultMiddleware =>
getDefaultMiddleware({
immutableCheck: false,
serializableCheck: false
}).concat(middlewares),
devTools: process.env.NODE_ENV === 'development'
});
store.asyncReducers = {};
export const injectReducer = (key, reducer) => {
if (store.asyncReducers[key]) {
return false;
}
store.asyncReducers[key] = reducer;
store.replaceReducer(createReducer(store.asyncReducers));
return store;
};
export const persistor = persistStore(store);
This is the createReducer():
import { combineReducers } from '#reduxjs/toolkit';
import auth from 'app/auth/store';
import fuse from './fuse';
import i18n from './i18nSlice';
const createReducer = asyncReducers => (state, action) => {
const combinedReducer = combineReducers({
auth,
fuse,
i18n,
...asyncReducers
});
/*
Reset the redux store when user logged out
*/
if (action.type === 'auth/user/userLoggedOut') {
state = undefined;
}
return combinedReducer(state, action);
};
export default createReducer;

Related

PersistGate null state

So I'm working on this Facebook clone and I see error
'Uncaught TypeError: user is null'.
Removing PersistGate component from my index.js file works, but I can't figure out how to solve the problem. And I need that component. Here's my code.
index.js
import React from "react";
import ReactDOM from "react-dom/client";
import "./index.css";
import App from "./App";
import authReducer from "./state";
import { configureStore } from "#reduxjs/toolkit";
import { Provider } from "react-redux";
import {
persistStore,
persistReducer,
FLUSH,
REHYDRATE,
PAUSE,
PERSIST,
PURGE,
REGISTER,
} from "redux-persist";
import storage from "redux-persist/lib/storage";
import { PersistGate } from "redux-persist/integration/react";
const persistConfig = { key: "root", storage, version: 1 };
const persistedReducer = persistReducer(persistConfig, authReducer);
const store = configureStore({
reducer: persistedReducer,
middleware: (getDefaultMiddleware) =>
getDefaultMiddleware({
serializableCheck: {
ignoredActions: [FLUSH, REHYDRATE, PAUSE, PERSIST, PURGE, REGISTER],
},
}),
});
const root = ReactDOM.createRoot(document.getElementById("root"));
root.render(
<React.StrictMode>
<Provider store={store}>
<PersistGate loading={null} persistor={persistStore(store)}>
<App />
</PersistGate>
</Provider>
</React.StrictMode>
);
import { createSlice } from "#reduxjs/toolkit";
const initialState = {
mode: "dark",
user: null,
token: null,
posts: [],
};
export const authSlice = createSlice({
name: "auth",
initialState,
reducers: {
setMode: (state) => {
state.mode = state.mode === "light" ? "dark" : "light";
},
setLogin: (state, action) => {
state.user = action.payload.user;
state.token = action.payload.token;
},
setLogout: (state) => {
state.user = null;
state.token = null;
},
setFriends: (state, action) => {
if (state.user) {
state.user.friends = action.payload.friends;
} else {
console.error("user friends non-existent :(");
}
},
setPosts: (state, action) => {
state.posts = action.payload.posts;
},
setPost: (state, action) => {
const updatedPosts = state.posts.map((post) => {
if (post._id === action.payload.post._id) return action.payload.post;
return post;
});
state.posts = updatedPosts;
},
},
});
export const { setMode, setLogin, setLogout, setFriends, setPosts, setPost } = authSlice.actions;
export default authSlice.reducer;
I was trying to follow with redux-persist documentation, but couldn't solve the problem.
It looks like the issue may be that you are creating a new persistor anytime the PersistGate component rerenders for whatever reason. It's the only part of your setup where I see it deviate from the documentation.
I suggest creating the persistor once outside any React/JSX code.
const persistConfig = { key: "root", storage, version: 1 };
const persistedReducer = persistReducer(persistConfig, authReducer);
const store = configureStore({
reducer: persistedReducer,
middleware: (getDefaultMiddleware) =>
getDefaultMiddleware({
serializableCheck: {
ignoredActions: [FLUSH, REHYDRATE, PAUSE, PERSIST, PURGE, REGISTER],
},
}),
});
const persistor = persistStore(store); // <-- create outside JSX
const root = ReactDOM.createRoot(document.getElementById("root"));
root.render(
<React.StrictMode>
<Provider store={store}>
<PersistGate loading={null} persistor={persistor}>
<App />
</PersistGate>
</Provider>
</React.StrictMode>
);

Cannot connect component to redux store

In my profile page I have 3 cards, which means 3 react-components.
I am new to React.js and recently set up redux in my application. So the problem is two of them (cards) successfully connected to redux store, but third card can't for unknown reasons, can you help me please?
Redux store just returns undefined only for Card3.js
Hero.js (Profile)
import React, { useState, useEffect } from "react"
import FadeIn from 'react-fade-in';
import { Redirect } from 'react-router-dom'
import { Container, Row } from 'react-bootstrap'
import { getUserProfile } from "../../services/user.service";
import { connect } from "react-redux";
import './profile.css'
import LCard1 from "./cards/card1/LCard1"
import Card1 from "./cards/card1/Card1"
import Card2 from "./cards/card2/Card2"
import Card3 from "./cards/card3/Card3"
const Hero = (props) => {
const [userInfo, setUserInfo] = useState({username: ''})
const [isLoading, setIsLoading] = useState(true)
const getUser = async () => {
console.log()
await getUserProfile(props.uid)
.then(res => {
setUserInfo(res)
setIsLoading(false)
})
}
useEffect(() => {
if (userInfo)
getUser()
}, [])
return (
<>
<FadeIn transitionDuration={1000}>
{props.authenticated ? (
<section className="profile-cards">
<Container fluid >
<Row>
{isLoading ? (
<LCard1 />
) : (
<Card1 user={userInfo} />
)}
<Card3 />
</Row>
<Row>
<Card2 />
</Row>
</Container>
</section>
) : (
<Redirect to="/signin" />
)}
</FadeIn>
</>
)
}
const mapStateToProps = (state) => {
return {
uid: state.authReducer.uid,
authenticated: state.authReducer.authenticated
}
}
const mapDispatchToProps = (dispatch) => {
return {
logout: () => {
dispatch({
type: 'SIGNOUT_SUCCESS'
})
}
}
}
export default connect(
mapStateToProps,
mapDispatchToProps
)(Hero)
Card3.js
import React from 'react'
import { connect } from "react-redux";
import CreateAdvertisement from './content/create.advert/CreateAdvertisement'
import MyMessages from './content/my.messages/MyMessages';
import MySettings from './content/my.settings/MySettings';
import MyVerfifcation from './content/my.verif/MyVerfifcation';
import './card3.css'
const Card3 = (props) => {
return (
<div>
<p>Test: {props.username}</p>
<section className="card3">
<div className="card3-box">
<div>
<MySettings />
</div>
</div>
</section>
</div>
)
}
const mapStateToProps = (state) => {
return {
key: state.authReducer.username
}
}
export default connect(
mapStateToProps
)(Card3)
store.js
import { configureStore } from '#reduxjs/toolkit'
import { persistReducer } from 'redux-persist'
import storage from 'redux-persist/lib/storage'
import thunk from 'redux-thunk'
import reducers from './reducers/root.reducer'
const persistConfig = {
key: 'root',
storage: storage,
blacklist: ['sidebarReducer']
}
const persistedReducer = persistReducer(persistConfig, reducers)
const store = configureStore({
reducer: persistedReducer,
devTools: process.env.NODE_ENV !== 'production',
middleware: [thunk]
})
export default store
index.js
import React from 'react'
import ReactDOM from 'react-dom'
import App from './components/App'
import { Provider } from 'react-redux'
import { PersistGate } from 'redux-persist/integration/react'
import { persistStore } from 'redux-persist'
import store from './store/store'
let persistor = persistStore(store)
ReactDOM.render(
<Provider store={store}>
<PersistGate loading={null} persistor={persistor}>
<App />
</PersistGate>
</Provider>,
document.getElementById('root')
);
import React, { Component } from 'react';
import { View, Text,ScrollView } from 'react-native';
import { Provider } from 'react-redux'
import store from './src/Redux/Store'
import MainNavigation from './src/components/Navigation/Navigation';
class App extends Component {
constructor(props) {
super(props);
this.state = {
};
}
render() {
return (
<Provider store={store}>
<MainNavigation/>
</Provider>
);
}
}
export default App;
First your all screens should under a navigation then
follow this code This will work for you Thanks.

React Native Net Info it works once

native-info package like tutorial but just enters once and initial render, I implemented App.js is my initial rendering page and I use redux and react nativagiton to App.js return method I confuse why console.warn triggered once and initial render, my App.js code like below
import {SafeAreaProvider} from 'react-native-safe-area-context';
import {Provider} from 'react-redux';
import {PersistGate} from 'redux-persist/integration/react';
import {NavigationContainer} from '#react-navigation/native';
import { SafeAreaProvider } from "react-native-safe-area-context";
import { Provider } from "react-redux";
import { PersistGate } from "redux-persist/integration/react";
import { NavigationContainer } from "#react-navigation/native";
export default function App() {
let navigator;
const [netInfo, setNetInfo] = useState("");
const [netConnection, setNetConnection] = useState(false);
useEffect(() => {
const unsubscribe = NetInfo.addEventListener((state) => {
setNetInfo({
isConnected: state.isConnected,
});
});
return () => {
unsubscribe();
};
}, []);
useEffect(() => {
console.warn(netInfo.isConnected);
if (netInfo.isConnected === undefined) {
if (netInfo.isConnected) {
setNetConnection(true);
} else {
setNetConnection(false);
}
}
}, [netInfo]);
return (
<Provider store={store}>
{netConnection && <RnModal show={netConnection} />}
<PersistGate loading={null} persistor={persistor}>
<SafeAreaProvider>
<NavigationContainer
ref={(nav) => {
navigator = nav;
}}
>
<Navigator />
</NavigationContainer>
</SafeAreaProvider>
</PersistGate>
</Provider>
);
}

Initial store is loaded when store is deleted from local storage redux-persist

I am using Next.js(SSr) with redux. I have successfully implemented react-persist with the nextjs.
the user state is updated after login and value is update in the redux store and simultaneously in the localStorage's store but whenever I delete the localStorage item which contains the store and refresh the page,the localStorage is filled by the first version of the store i.e the initial store.
I though there might be problem in re hydration but i think PersistGate is handling it efficiently.
Can someone point out what went wrong in implementation ?
thanks in advance :)
_app.js
import withRedux from 'next-redux-wrapper'
import { withRouter } from 'next/router'
import { Provider } from 'react-redux'
import App from 'next/app'
import Layout from 'components/Layout'
import createStore from 'store/createStore'
import { persistStore } from 'redux-persist'
import { PersistGate } from 'redux-persist/integration/react'
class MyApp extends App {
static async getInitialProps ({ Component, ctx }) {
return {
pageProps: Component.getInitialProps
? await Component.getInitialProps(ctx)
: {}
}
}
constructor(props) {
super(props)
this.persistor = persistStore(props.store)
}
render () {
const { Component, pageProps, store, router } = this.props
return (
<>
<Provider store={store}>
<PersistGate
loading={<Component {...pageProps} />}
persistor={this.persistor}
>
<Layout>
<Component router={router} {...pageProps} />
</Layout>
</PersistGate>
</Provider>
</>
)
}
}
export default withRedux(createStore, {debug: true})(
withRouter(MyApp)
)
createStore.js
import Immutable from 'immutable'
import thunkMiddleware from 'redux-thunk'
import { createLogger } from 'redux-logger'
import { composeWithDevTools } from 'redux-devtools-extension'
import { createStore, applyMiddleware } from 'redux'
import { persistReducer } from 'redux-persist'
import storage from 'redux-persist/lib/storage'
import config from 'config'
import rootReducer from '../reducers'
const persistConfig = {
key: 'primary',
storage,
whitelist: ['user'],
}
const persistedReducer = persistReducer(persistConfig, rootReducer)
function createMiddlewares ({ isServer }) {
const middlewares = [
thunkMiddleware
]
if (config.env === 'development' && typeof window !== 'undefined') {
middlewares.push(createLogger({
level: 'info',
collapsed: true,
stateTransformer: (state) => {
const newState = {}
for (const i of Object.keys(state)) {
if (Immutable.Iterable.isIterable(state[i])) {
newState[i] = state[i].toJS()
} else {
newState[i] = state[i]
}
}
return newState
}
}))
}
return middlewares
}
function immutableChildren (obj) {
const state = {}
Object.keys(obj).forEach((key) => {
state[key] = Immutable.fromJS(obj[key])
})
return state
}
export default (initialState = {}, context) => {
const { isServer } = context
const middlewares = createMiddlewares({ isServer })
const state = immutableChildren(initialState)
return createStore(
persistedReducer,
state,
composeWithDevTools(applyMiddleware(...middlewares))
)
}
Img: initial store loaded instead of updated store after localStorage item is removed and page is refreshed
If you are using the redux-persist you no need to bind the PersistGate with provider...you can remove it and try again hope it will solve your issue...This is because you are already wrapping the component with withRedux hook.
return (
<PersistGate
loading={<Component {...pageProps} />}
persistor={this.persistor}
>
<Layout>
<Component router={router} {...pageProps} />
</Layout>
</PersistGate>
)
This will be enough

React Native with Redux-Persist , PersistGate inifinite loading

I'm working on an app in react native and must work with Redux-Persist. I have the store configuration set up, no errors occur but the rehydration never happens and the persistentGate is infinitely in the loading state.
Here is my store.js
import { createStore, combineReducers } from 'redux';
import { persistStore, persistReducer } from 'redux-persist';
import storage from 'redux-persist/lib/storage';
import entriesReducer from './reducers/entries';
import autoMergeLevel2 from 'redux-persist/lib/stateReconciler/autoMergeLevel2';
const rootReducer = combineReducers({
entries : entriesReducer
});
const persistConfig = {
key: 'root',
storage: storage,
stateReconciler: autoMergeLevel2 // see "Merge Process" section for details.
};
const pr = persistReducer(persistConfig, rootReducer);
const configureStore = () => {
const store = createStore(rootReducer);
const persistor = persistStore(store);
return { persistor, store };
};
export default configureStore;
And my index.js
import React from 'react';
import { AppRegistry } from 'react-native';
import {Provider} from 'react-redux';
import App from './App';
import configureStore from './src/store/configureStore';
import { PersistGate } from 'redux-persist/lib/integration/react';
const store = configureStore();
const RNRedux = () => (
<Provider store={store.store}>
<PersistGate loading={<App />} persistor={store.persistor}>
<App/>
</PersistGate>
</Provider>
);
AppRegistry.registerComponent('PTM', () => RNRedux);
Any help will be very much appreciated, I've been trying to set this up for days now with no success. Previously I would have to deal with errors but now I don't see any and it still refuses to work, I simply don't know where to look for the fault.
Edit:
App.js file
import React from 'react';
import { View, Text, Button, StatusBar } from 'react-native';
import { StackNavigator } from 'react-navigation';
import {connect} from 'react-redux';
import NavBar from './src/components/NavBar/NavBar';
import DayPicker from './src/components/DayPicker/DayPicker';
import TotalTime from './src/components/TotalTime/TotalTime';
import HomeScreen from './screens/HomeScreen';
import DetailsScreen from './screens/DetailsScreen';
import EntriesList from './src/components/EntriesList/EntriesList';
var x = null;
const RootStack = StackNavigator(
{
Home: {
screen: HomeScreen,
},
Details: {
screen: DetailsScreen,
},
},
{
initialRouteName: 'Home',
}
);
export default class App extends React.Component {
render() {
return <RootStack />;
}
}
And my HomeScreen is using this:
const mapStateToProps = state => {
return {
data : state.entries.data,
entriesPerDay : state.entries.entriesPerDay,
pickedDate : state.entries.pickedDate,
total: state.entries.total
};
};
const mapDispatchToProps = dispatch => {
return {
onPickDate: (day) => dispatch(pickDay(day)),
onDataSet: (data) => dispatch(setData(data))
};
};
export default connect(mapStateToProps, mapDispatchToProps)(HomeScreen);

Categories

Resources