-
Hello! I learn I to use Hooks and I decide to create a cart on my web app, so I implement with redux-persist to access to my cart content from every where even if the user refresh the page. But at first for some reasons the useSelector do not re-render, even if the obj change in the composeWithDevTools console... In the cart page (with the client's selected stuff), I got cross next to each articles to delete then if the user decide to take out the article from him cart. Oddly it's work (not really) if I look on the composeWithDevTools, I can see my article is delete from my articleList with articleAdd (action add the new array without article deleted). The front is not re-render... And if I use articleDelete the whole articleList is delete and replace by an empty List, and the re-render WORK! I follow this implementation : https://github.com/vercel/next.js/tree/canary/examples/with-redux-persist so it's probably because i'm novice with Hook and nextJs and I really don't find the response to solve it and raise... Did I use useState , useSelector and useEffect correctly ? (log : redux-persist failed to create sync storage. falling back to noop storage.) that's the react's function taht's doesn't work : export default function CartArticleRow({
ulrImage,
Name,
Price,
courseId,
store,
}: Props): ReactElement {
const dispatch = useDispatch()
const [SpliceCourseId, setSpliceCourseId] = useState<number | null>(null);
useEffect(() => {
if (typeof SpliceCourseId === 'number') {
var newList: ICourse[] = store.articleList;
if (newList && newList.length > 0) {
for (let index: number = 0; index < newList.length; index++) {
if (newList[index].course_id === SpliceCourseId)
newList.splice(index, 1);
}
dispatch(articleAdd(newList));
// dispatch(articleDelete()); => this one work not the action above
}
}
}, [SpliceCourseId]);
return (
<div
className="px-2 mt-2"
style={{ background: "#1c457714", borderRadius: "4px" }}
>
<div className="display-flex">
<div className="">
<div className="LineItem-imageContainer mr4 LineItem-imageContainer mr4 flex-item width-fixed">
<img src={ulrImage} alt="" className="LineItem-image" />
</div>
</div>
<div className="text-right my-auto" style={{ width: "100%" }}>
<span
onClick={() => {
setSpliceCourseId(courseId);
}}
>
X
</span>
</div>
</div>
</div>
);
} App : nextjs, react and typeScript package.json : {
"name": "showcase",
"version": "0.1.0",
"private": true,
"scripts": {
"dev": "next dev",
"build": "next build",
"start": "next start"
},
"dependencies": {
"@emotion/styled-base": "^10.0.31",
"@stripe/react-stripe-js": "^1.1.2",
"@stripe/stripe-js": "^1.8.0",
"@types/react-redux": "^7.1.9",
"axios": "^0.19.2",
"next": "latest",
"next-redux-wrapper": "^6.0.2",
"react": "^16.13.1",
"react-dom": "^16.13.1",
"react-redux": "^7.2.1",
"react-router-dom": "^5.2.0",
"react-scroll": "^1.8.0",
"react-spring": "^8.0.27",
"react-use": "^15.3.3",
"redux": "^4.0.5",
"redux-persist": "^6.0.0",
"redux-thunk": "^2.3.0",
"sitemap": "^6.2.0",
"stripe": "^8.79.0",
"swr": "^0.2.3"
},
"devDependencies": {
"@types/node": "^14.0.27",
"@types/react": "^16.9.43",
"eslint-plugin-react-hooks": "^4.0.8",
"prettier": "^2.0.5",
"typescript": "^3.9.7"
},
"extends": [
"plugin:react-hooks/recommended"
],
"plugins": [
"react-hooks"
],
"rules": {
"react-hooks/rules-of-hooks": "error",
"react-hooks/exhaustive-deps": "warn"
}
} |
Beta Was this translation helpful? Give feedback.
Replies: 9 comments 25 replies
-
Getting the same log. |
Beta Was this translation helpful? Give feedback.
-
This log occurs on the server-side (when you import storage from import createWebStorage from "redux-persist/lib/storage/createWebStorage";
const createNoopStorage = () => {
return {
getItem(_key) {
return Promise.resolve(null);
},
setItem(_key, value) {
return Promise.resolve(value);
},
removeItem(_key) {
return Promise.resolve();
},
};
};
const storage = typeof window !== "undefined" ? createWebStorage("local") : createNoopStorage();
export default storage; Use this storage in the config instead of |
Beta Was this translation helpful? Give feedback.
-
I'm getting this same error, but my entire Redux instantiation is hidden behind code which should force it to run on the client only... import App, { store } from 'app';
import { useEffect, useState } from 'react';
import { GlobalStyles } from 'components/Layouts/AppGlobalStyles';
import { Provider } from 'react-redux';
function AirApp() {
const [isMounted, setIsMounted] = useState(false);
useEffect(() => {
setIsMounted(true);
}, []);
if (!isMounted) return null;
return (
<Provider store={store}>
<GlobalStyles />
<App />
</Provider>
);
}
export default AirApp; any ideas why it still attempts to build on the server? edit: I tried simply following your suggestion anyways: import { Persistor, persistReducer, persistStore } from 'redux-persist';
import { Store, applyMiddleware, createStore } from 'redux';
import createSagaMiddleware, { Task } from 'redux-saga';
import createRootReducer from './rootReducer';
import { reactors } from './reactors';
import createWebStorage from 'redux-persist/lib/storage/createWebStorage';
import migrate from 'app/store/stateMigrations';
import rootSagas from 'app/store/sagas';
import subscribeToStore from 'app/store/subscribeToStore';
import thunkMiddleware from 'redux-thunk';
export interface SagaStore extends Store {
sagaTask?: Task;
}
const bindMiddleware = (middleware: any[]) => {
if (process.env.NODE_ENV !== 'production') {
const { composeWithDevTools } = require('redux-devtools-extension');
return composeWithDevTools(applyMiddleware(...middleware));
}
return applyMiddleware(...middleware);
};
const createNoopStorage = () => {
return {
getItem(_key: string) {
return Promise.resolve(null);
},
setItem(_key: string, value: any) {
return Promise.resolve(value);
},
removeItem(_key: string) {
return Promise.resolve();
},
};
};
export let persistor: Persistor;
export const makeStore = () => {
const sagaMiddleware = createSagaMiddleware();
const middleware = [sagaMiddleware, thunkMiddleware];
const storage = typeof window !== 'undefined' ? createWebStorage('local') : createNoopStorage();
const persistConfig = {
key: 'primary',
version: 9,
storage,
migrate,
};
const persistedReducer = persistReducer(persistConfig, createRootReducer());
const store = createStore(persistedReducer, bindMiddleware(middleware));
persistor = persistStore(store);
(store as SagaStore).sagaTask = sagaMiddleware.run(rootSagas);
subscribeToStore(store, [...reactors]);
return store;
}; but I still get the same error as OP |
Beta Was this translation helpful? Give feedback.
-
Thank you so much. It did work in my new Next13. But creating web store I have to add this "use client" on top of the storage.ts
|
Beta Was this translation helpful? Give feedback.
-
Best way to do in nextjs w/ app router 13.4 >, is to call it inside your app/layout.tsx, for some reason I had to do it this way in order to completely code split it. ################################################################################ const userProfilePersistConfig = { const rootReducer = combineReducers({ const persistedReducer = persistReducer(userProfilePersistConfig, rootReducer); export const store = configureStore({ export type RootState = ReturnType; export const useAppDispatch = () => useDispatch(); ################################################################################ const persistor = persistStore(store); export default function ReduxProvider({children}: { children: React.ReactNode }) { import dynamic from "next/dynamic"; export const metadata = { export default function RootLayout({children}: { |
Beta Was this translation helpful? Give feedback.
-
Redux persist storage only work on client side just fix by dynamic import in layout.tsx
|
Beta Was this translation helpful? Give feedback.
-
I am using next js appRouter. I ve implemented the redux according oficial docs. `import { configureStore } from '@reduxjs/toolkit' export const makeStore = () => { // Infer the type of makeStore redux is working, but the persist is not working with such implementation of redux. If I use redux as usual, not using HOF; the persist work. However, such redux does not shown in reduxDevTools. are there any solution for such problem? and what redux implementation should we use? |
Beta Was this translation helpful? Give feedback.
-
I am using Next.js 14.2.5 along with Redux Toolkit ^2.2.7 on my project. I want to write this for anyone confused about this as many answers on the internet are just wrong. The accepted answer on this thread is NOT correct and will still create noop storage, just without an error message on the console. The reason for this happening is because Next.js always compiles components on the server EVEN if you have the export default function StoreProvider({ children }: StoreProviderProps) {
const storeRef = useRef<AppStore>()
const [loading, setLoading] = useState<boolean>(true)
if (!storeRef.current) {
// Create the store instance for the first time this renders
storeRef.current = makeStore()
}
// Any references outside of useEffect will return a ReferenceError,
// which leads to redux-persist's error.
useEffect(() => {
localStorage.getItem("mykey") // works!
// or sessionStorage, whichever you need.
// other client-side logic...
}, [])
if (loading) {
return <CircularProgress/>
}
return (
<Provider store={storeRef.current}>
{children}
</Provider>
)
} So for any code that needs to interact with client-side APIs, ensure you do it all within tldr;
|
Beta Was this translation helpful? Give feedback.
This log occurs on the server-side (when you import storage from
redux-persist/lib/storage
) because you cannot create the local storage in Node.js. Here is my workaround:Use this storage in the config instead of
redux-persist/lib/storage