Redux Persist using Redux Toolkit in React - react-redux

I wanna store states after refreshing the page, so I used Redux Persist and followed the instructions at LogRocket, I failed again and again because my configureStore is different. Can you please tell me how to do it?
Here is my store.js
// store.js
import { configureStore } from "#reduxjs/toolkit";
import appSlice from './appSlice';
const store = configureStore({
reducer: {
app: appSlice.reducer,
}
});
export default store
Here is my index.js
// index.js
import React from 'react';
import ReactDOM from 'react-dom/client';
import { Provider } from 'react-redux';
import { App } from './App';
import store from './data/store';
import './index.css'
import reportWebVitals from './reportWebVitals';
import {BrowserRouter as Router, Routes, Route } from 'react-router-dom';
// const store = configureStore({ reducer: App });
// const store = createStore(Reducer)
const root = ReactDOM.createRoot(document.getElementById('root'));
root.render(
<React.StrictMode>
<Provider store={store}>
<Router>
<Routes>
<Route path="/*" element={<App/>} />
</Routes>
</Router>
</Provider>
</React.StrictMode>
);
reportWebVitals();
Thank you in advance!
When I follow the instructions, console shows couldn't find app store

// create store.js like this
import { combineReducers } from 'redux';
import { configureStore } from '#reduxjs/toolkit';
import { persistStore, persistReducer } from 'redux-persist';
import storage from 'redux-persist/lib/storage'; // defaults to localStorage for web
// add the reducers that need to be persisted
const reducersToPersist = [];
const persistConfig = {
key: 'root',
storage,
whitelist: reducersToPersist
};
const reducers = combineReducers({
// Your reducers
});
const persistedReducer = persistReducer(persistConfig, reducers);
const store = configureStore({
reducer: persistedReducer,
});
const persistor = persistStore(store);
export { store, persistor };
in your root file
import { PersistGate } from 'redux-persist/integration/react';
import { Provider } from 'react-redux';
import { persistor, store } from './store';
const App = () => {
return (
<Provider store={store}>
<PersistGate loading={null} persistor={persistor}>
{/* Your Project routes */}
</PersistGate>
</Provider>
);
};
export default App;

Related

How do i use prototype.$loading in vue 3 and vuex application?

I am using Element-plus ui for this crud app. Which is build in laravel -8 and vue -3 But when ever i am trying to access prototype.$loading or $notify is is showing the error Cannot read properties of undefined (reading '$loading')
Now how i will do?
I am new in vue 3.
action.js
import axios from "axios";
import { createApp } from 'vue';
let loader = null;
function showLoader(text = "Loading") {
loader = createApp.prototype.$loading({
lock: true,
text: text,
spinner: 'el-icon-loading',
background: 'rgb(255,255,255,0.85)',
})
}
function hideLoader() {
loader.close();
}
export const saveStudent = ({commit}, payload) => {
let url = `/save-student`;
showLoader('Saving Student Data');
axios.post(url, payload)
.then(res => {
createApp.prototype.$notify({
title: 'Success',
message: 'Student Created Successfully',
type: 'success'
});
hideLoader();
window.location.href = "/students";
})
}
app.js
import './bootstrap';
import { createApp } from 'vue';
import ElementPlus from 'element-plus'
import 'element-plus/dist/index.css'
import {store} from './store/store.js'
import axios from "axios";
const app = createApp({});
import StudentForm from './components/student/StudentForm.vue';
app.component('student-form-component', StudentForm);
app.config.globalProperties.$axios = axios;
app.use(ElementPlus);
app.use(store);
app.mount('#app');
store.js
import {createStore} from "vuex";
import * as getters from './getters.js'
import * as mutations from './mutations.js'
import * as actions from './actions.js'
export const store = createStore({
modules: {},
state: {},
mutations,
getters,
actions,
})

Cache is not persisted on refresh

I am working on a nextJS with react-apollo and apollo-client. I am using apollo-cache-persist to persist my data. But when I refresh the page, data are lost.
I tried the solution provided here but sadly didn't work.
import React from "react";
import Head from "next/head";
import App, { Container } from "next/app";
import { ApolloClient } from "apollo-client";
import {ApolloProvider} from "react-apollo";
import { InMemoryCache } from "apollo-cache-inmemory";
import { createHttpLink } from "apollo-link-http";
import { withClientState } from "apollo-link-state";
import fetch from "node-fetch";
import { resolvers, defaults } from "../Container/resolvers";
import { ApolloLink } from "apollo-link";
const cache = new InMemoryCache();
const stateLink = withClientState({
cache,
defaults,
resolvers
});
const httpLink = new createHttpLink({
fetch,
uri: "http://localhost:4444/",
headers: {
"Content-Type": "application/json"
}
});
export const client = new ApolloClient({
link: ApolloLink.from([stateLink, httpLink]),
cache
});
export default class MyApp extends App {
static async getInitialProps({ Component, ctx }) {
return {
pageProps: {
// Call page-level getInitialProps
...(Component.getInitialProps
? await Component.getInitialProps(ctx)
: {})
}
};
}
async ComponentWillMount() {
await persistCache({
cache
});
}
render() {
const { Component, pageProps, store } = this.props;
return (
<ApolloProvider client={client}>
<Container>
<Head>
<title>HELLO WORLD</title>
</Head>
<Component {...pageProps} />
</Container>
</ApolloProvider>
);
}
}
I expect the cache to persist but the cache returns nothing on reload.

typeerror _this.store is not defined react redux

I am currently following this tutorial (https://medium.com/#viewflow/full-stack-django-quick-start-with-jwt-auth-and-react-redux-part-ii-be9cf6942957) which is essentially a guide on implementing JWT authentication with Django REST Framework and React.
However, upon compiling the code given on the repository posted by the author(s), I've been getting a specific error:
"TypeError: _this.store is undefined"
and after trawling through the web, I've not been able to find an answer to the problem I face.
Would appreciate any help I can get, thank you!
This tutorial uses react-router-redux which is deprecated. What you could do is use connected-react-router instead. So your src/index.js would look like
import React from 'react';
import ReactDOM from 'react-dom';
import { ConnectedRouter } from 'connected-react-router';
import { Provider } from 'react-redux';
import App from './App';
import configureStore, { history } from './store';
const store = configureStore();
ReactDOM.render(
<Provider store={store}>
<ConnectedRouter history={history}>
<App />
</ConnectedRouter>
</Provider>,
document.getElementById('root')
Your store would now take a preloadedState variable like
import storage from 'redux-persist/es/storage';
import { createBrowserHistory } from 'history';
import { apiMiddleware } from 'redux-api-middleware';
import { applyMiddleware, compose, createStore } from 'redux';
import { createFilter } from 'redux-persist-transform-filter';
import { persistReducer, persistStore } from 'redux-persist';
import { routerMiddleware } from 'connected-react-router';
import rootReducer from './reducers';
export const history = createBrowserHistory();
export default function configureStore(preloadedState) {
const persistedFilter = createFilter('auth', ['access', 'refresh']);
const reducer = persistReducer(
{
key: 'polls',
storage: storage,
whitelist: ['auth'],
transforms: [persistedFilter],
},
rootReducer(history)
);
const store = createStore(
reducer,
preloadedState,
compose(applyMiddleware(apiMiddleware, routerMiddleware(history)))
);
persistStore(store);
return store;
}
Now your root reducer will take history as an argument:
import { combineReducers } from 'redux';
import { connectRouter } from 'connected-react-router';
import auth, * as fromAuth from './auth.js';
export default history =>
combineReducers({
router: connectRouter(history),
});
export const isAuthenticated = state => fromAuth.isAuthenticated(state.auth);
...

TypeError: store.getState is not a function in react-redux

I followed the instructions and created the store from this library
https://github.com/jesperorb/redux-cart
src/store/index.js:
import { createStore } from 'redux';
//Import our rootreducer from '../reducers/index.js' this hold our whole state
import rootReducer from '../reducers/index.js';
/**
* #param {Object} initialState
*/
export default function store() {
return createStore(
rootReducer,
window.__REDUX_DEVTOOLS_EXTENSION__ && window.__REDUX_DEVTOOLS_EXTENSION__()
);
}
```
src/actions/cart-actions.js:
/** We don't have to use the variable 'payload', we can also just name it: 'item'
* #param {Object} item
*/
export function addToCart(item) {
return {
type: 'ADD',
item: item
};
}
export function removeFromCart(item) {
return {
type: 'REMOVE',
item: item
};
}
src/index.js:
import React from 'react';
import ReactDOM from 'react-dom';
import './index.css';
import App from './App';
import { Provider } from 'react-redux';
import registerServiceWorker from './registerServiceWorker';
import store from './store/index.js';
ReactDOM.render(
<Provider store={store}>
<App />
</Provider>, document.getElementById('root'));
registerServiceWorker();
but i get the error TypeError: store.getState is not a function. Can someone propose what steps should i look into first?
Looks like you forgot to create a store object in index.js
import React from 'react';
import ReactDOM from 'react-dom';
import './index.css';
import App from './App';
import { Provider } from 'react-redux';
import registerServiceWorker from './registerServiceWorker';
import Store from './store/index.js';
// forgot to create store obj
const store = Store();
ReactDOM.render(
<Provider store={store}>
<App />
</Provider>, document.getElementById('root'));
registerServiceWorker();

Using redux-connected component as screen in StackNavigator

I'm creating an react native app using create-react-native-app, react-navigation and react-redux. I'm trying to add a redux-connected component as a screen into a nested StackNavigator (though the nesting seems to not make a difference, it doesn't work either way) and consistently am getting an error message saying Route 'MilkStash' should declare a screen. When I remove the redux connection from the MilkStash.js file, everything works fine. Any idea how to get this working?
App.js
import React, { Component } from 'react';
import { StyleSheet, Text, View } from 'react-native';
import { Provider } from 'react-redux';
import { createStore } from 'redux';
import rootReducer from './src/reducers';
import AppWithNavigation from './src/AppWithNavigation';
export default () => (
<Provider store = {createStore(rootReducer)}>
<AppWithNavigation />
</Provider>
);
AppWithNavigation.js
import React, { Component } from 'react';
import { connect } from 'react-redux';
import { StyleSheet, Text, View, Image, Button } from 'react-native';
import { DrawerNavigator, StackNavigator } from 'react-navigation';
import MilkStash from './screens'
import { StatsScreen, FAQScreen, AddMilk, AccountScreen } from './screens';
export default class AppWithNavigation extends React.Component {
render() {
return (
<MenuNavigator />
);
}
}
const MilkNavigator = StackNavigator(
{ Milk: { screen: MilkStash},
AddMilk: { screen: AddMilk }
},
);
const AccountNavigator = StackNavigator(
{ Account: {screen: AccountScreen}}
);
const StatsNavigator = StackNavigator(
{ Stats: {screen: StatsScreen }}
);
const FAQNavigator = StackNavigator(
{ FAQ: {screen: FAQScreen}}
)
const MenuNavigator = DrawerNavigator({
Milk: { screen: MilkNavigator},
Account: {screen: AccountNavigator},
Stats: {screen: StatsNavigator},
FAQ: {screen: FAQNavigator},
}
);
const styles = StyleSheet.create({
container: {
flex: 1,
justifyContent: 'center',
backgroundColor: '#ecf0f1',
}
});
MilkStash.js
import React, {Component} from 'react';
import { StyleSheet, Text, View} from 'react-native';
import { StackNavigator } from 'react-navigation';
import { connect } from 'react-redux';
import { Milk } from '../../core/models/milk';
import styles from './styles.js';
export class MilkStash extends Component {
constructor(props){
super(props);
}
render() {
return (
<View style={styles.container}>
....displaying data goes here
</View>
)
}
}
function mapStateToProps(state){
return{
milkStash: state.milkStash
}
}
function mapDispatchToProps(dispatch){
return {
addMilk: (milk) => dispatch(addMilk(milk)),
}
}
export default connect(mapStateToProps, mapDispatchToProps)(MilkStash);
milk-reducer.js
import {ADD_MILK} from '../constants';
const milkReducer = (state = {milkStash: []}, action = {}) => {
switch(action.type){
case ADD_MILK:
var item = action.payload;
return state
.update('milkStash', (milkStash) =>
{
var milkStashCopy = JSON.parse(JSON.stringify(milkStash));
milkStashCopy.concat(item);
return milkStashCopy;
});
default:
return state;
}
}
export default milkReducer;
reducers.js
export * from './milk.js';
import milkReducer from './milk';
import { combineReducers } from 'redux';
export default rootReducer = combineReducers({
milk: milkReducer
});
I figured out the answer and thought I would help prevent someone else struggling with this for 3 days. The issue had to do with the way I was importing the exports from MilkStash.js. Apparently using import MilkStash from './screens' will cause the error but changing it to import MilkStashContainer from './screens/MilkStash/MilkStash.js will fix the problem.

Resources