Firebase Auth not working properly with React 18 - firebase

My environment
Operating System version: macOS Monterey 12.3.1
Browser version: Chrome 100.0.4896.60
Firebase SDK version: 9.6.10
Firebase Product: auth
Relevant Code:
// src/index.js
import React from 'react';
import { createRoot } from 'react-dom/client';
import { BrowserRouter as Router } from 'react-router-dom';
import './styles/styles.scss';
import App from './App/App';
import reportWebVitals from './reportWebVitals';
import { ThemeContextProvider } from './contexts/themeContext';
import './i18n';
import { AppContextProvider } from './contexts/appContext';
import { AuthContextProvider } from './contexts/authContext';
const container = document.getElementById('root');
const root = createRoot(container);
root.render(
<Router>
<React.StrictMode>
<AppContextProvider>
<ThemeContextProvider>
<AuthContextProvider>
<App />
</AuthContextProvider>
</ThemeContextProvider>
</AppContextProvider>
</React.StrictMode>
</Router>,
);
reportWebVitals();
import {
initializeAuth,
GoogleAuthProvider,
browserLocalPersistence,
indexedDBLocalPersistence,
browserSessionPersistence,
browserPopupRedirectResolver,
} from 'firebase/auth';
import app from './firebaseApp';
const auth = initializeAuth(app, {
persistence: [indexedDBLocalPersistence, browserLocalPersistence, browserSessionPersistence],
popupRedirectResolver: browserPopupRedirectResolver,
});
const googleProvider = new GoogleAuthProvider().setCustomParameters({
prompt: 'select_account',
});
const actionCodeSettings = {
url: process.env.REACT_APP_URL,
};
export { googleProvider, actionCodeSettings };
export default auth;
There were no problems when using React 17. Upgrading to React 18, every time we open the page, the user acts as if he is not logged in. Refreshing the page logs out directly.

Related

redux persist localstorage data is vanished by reload

I am using redux persist to store my redux state in local storage. The redux persist is working to store data in localstorage, but when I reload the page the data is gone from local storage and state. Here is link of the repo of project on which I am working https://github.com/bakarfreelancer/jccs-frontend. And The below is my reducer and store Index file.
//Reducer/Index.js
import { configureStore } from "#reduxjs/toolkit";
import { combineReducers, compose } from "redux";
import storage from "redux-persist/lib/storage";
import {
persistReducer,
FLUSH,
REHYDRATE,
PAUSE,
PERSIST,
PURGE,
REGISTER,
} from "redux-persist";
import thunk from "redux-thunk";
import usersReducer from "./usersReducer";
const persistConfig = {
key: "persistroot",
version: 1,
storage,
};
const rootReducer = combineReducers({ users: usersReducer });
const persistedReducer = persistReducer(persistConfig, rootReducer);
const store = configureStore({
reducer: persistedReducer,
middleware: (getDefaultMiddleware) =>
getDefaultMiddleware({
serializableCheck: {
ignoredActions: [FLUSH, REHYDRATE, PAUSE, PERSIST, PURGE, REGISTER],
},
}),
});
export default store;
//
//
//
//Index.js
import React from "react";
import ReactDOM from "react-dom/client";
import App from "./App";
import reportWebVitals from "./reportWebVitals";
import "bootstrap/dist/css/bootstrap.css";
import { Provider } from "react-redux";
import { BrowserRouter } from "react-router-dom";
import { persistStore } from "redux-persist";
import { PersistGate } from "redux-persist/integration/react";
import store from "./reducers";
let persistor = persistStore(store);
const root = ReactDOM.createRoot(document.getElementById("root"));
root.render(
<React.StrictMode>
<Provider store={store}>
<PersistGate persistor={persistor}>
<BrowserRouter>
<App />
</BrowserRouter>
</PersistGate>
</Provider>
</React.StrictMode>
);
reportWebVitals();
I want to store the redux state (which is updated after user login) in localstorage or some other storage like cookies. I checked the official documentation and I think my code is same.
The problem is solved by using redux toolkit documentation.
So by implementing the createSlice method for creating my reducers it works perfectly.

A module cannot have multiple default exports.ts(2528)

I'm trying to implement switch case for my products in Redux. I'm importing the cases from a file named productConstants using multiple export defaults. Problem is, the moment I write multiple lines, my screen turns red with this error 'A module cannot have multiple default exports.ts(2528)'
productReducers.js file
ALL_PRODUCTS_REQUEST,
ALL_PRODUCTS_SUCCESS,
ALL_PRODUCTS_FAIL} from '../constants/productConstants'
export const productsReducer = (state ={ products: [] }, action => {
switch(action.type) {
default:
return state;
}
})
my productConstants.js file
```export default ALL_PRODUCTS_REQUEST = 'ALL_PRODUCT_REQUEST'
export default ALL_PRODUCTS_SUCCESS = 'ALL_PRODUCT_SUCCESS'
export default ALL_PRODUCTS_FAIL = 'ALL_PRODUCT_FAIL'
export default CLEAR_ERRORS = 'CLEAR_ERRORS'
here is my store.js file
```//import { configureStore } from '#reduxjs/toolkit'
import { createStore, combineReducers, applyMiddleware } from 'redux';
import thunk from 'redux-thunk';
import { composeWithDevTools } from 'redux-devtools-extension'
const reducer = combineReducers({
})
let initialState = {}
const middleware = [thunk];
const store = createStore( reducer, initialState, composeWithDevTools(applyMiddleware(...middleware)))
export default store;
and finally, my index.js file
```import React from "react";
import ReactDOM from "react-dom";
import App from "./App";
import { Provider } from 'react-redux'
import store from './store'
ReactDOM.render(
<Provider store={store}>
<App />
</Provider>,
document.getElementById('root')
);
How do I do away with this error? A module cannot have multiple default exports.ts(2528)
productConstants.js(1, 1): The first export default is here.
A module can have only one default export per module, meaning that in one JS file only one variable (or function) can be exported with the default keyword.
You can convert them all to named export:
export const ALL_PRODUCTS_FAIL = 'ALL_PRODUCT_FAIL'

Migrating from Vite with ReactJS to Nexjs, SyntaxError: Cannot use import statement outside a module

I am migrating a vite and react project to Nextjs. This project uses redux-persist.
When migrating and running code it shows this error.
I was trying several solutions found on the net but none helped.
I created a new NextJS project from scratch and ended with the same error.
import { FLUSH, PAUSE, PERSIST, PURGE, REHYDRATE, DEFAULT_VERSION } from './constants';
SyntaxError: Cannot use import statement outside a module
My _app.tsx code
import { persistor, store } from "app/store";
import { Provider } from "react-redux";
function MyApp({ Component, pageProps }: AppProps) {
return (
<Provider store={store}>
<Component {...pageProps} />
</Provider>
);
}
export default MyApp;
app/store.ts
import { configureStore, combineReducers } from "#reduxjs/toolkit";
import {
persistStore,
persistReducer,
FLUSH,
REHYDRATE,
PAUSE,
PERSIST,
PURGE,
REGISTER,
} from "redux-persist";
import storage from "redux-persist/lib/storage";
import logger from "redux-logger";
import rootReducers from "./rootReducers";
const isDev = process.env.NODE_ENV === "development";
const persistConfig = {
key: "root",
version: 1,
storage,
whitelist: ["darkmode"],
};
const rootReducer = combineReducers(rootReducers);
const persistedReducer = persistReducer(persistConfig, rootReducer);
const middlewareLogger: any = !!isDev ? logger : [];
export const store = configureStore({
reducer: persistedReducer,
middleware: (getDefaultMiddleware) =>
getDefaultMiddleware({
serializableCheck: {
ignoredActions: [FLUSH, REHYDRATE, PAUSE, PERSIST, PURGE, REGISTER],
},
}).concat(middlewareLogger),
});
export let persistor = persistStore(store);
export type RootState = ReturnType<typeof store.getState>;
export type AppDispatch = typeof store.dispatch;
Someone got it to work with NextJS?
Thanks!

Issue while implementing firebaseUi auth in a nextjs project ? [error : window is not defined]

I'm trying to setup firebase Auth into my nextjs project (it looks like the firebase documentation is not up-to-date via the release of the getAuth method).
While using firebaseUi (to get the automatic styling of the different auth providers), I get this error :
Here is the code (i'm just trying to render the firebaseUi component for now) :
import { initializeApp } from "firebase/app";
import { getFirestore } from "firebase/firestore";
import { getAuth } from "firebase/auth";
const firebaseConfig = {
apiKey: process.env.NEXT_PUBLIC_FIREBASE_API_KEY,
authDomain: process.env.NEXT_PUBLIC_FIREBASE_AUTH_DOMAIN,
projectId: process.env.NEXT_PUBLIC_FIREBASE_PROJECT_ID,
storageBucket: process.env.NEXT_PUBLIC_FIREBASE_STORAGE_BUCKET,
messagingSenderId: process.env.NEXT_PUBLIC_FIREBASE_MESSAGING_SENDER_ID,
appId: process.env.NEXT_PUBLIC_FIREBASE_APP_ID,
measurementId: process.env.NEXT_PUBLIC_FIREBASE_MEASUREMENT_ID
};
// Initialize Firebase
const app = initializeApp(firebaseConfig);
// Initialize Cloud Firestore
const db = getFirestore(app);
// Initialize Firebase Authentication
const auth = getAuth(app);
export { db, auth }
Then in a template page for signin :
import { NavBar } from '../components';
import { StyledFirebaseAuth } from 'react-firebaseui/StyledFirebaseAuth';
import { auth } from '../firebase/initFirebase';
import { GoogleAuthProvider } from 'firebase/auth';
const firebaseui = require('firebaseui')
// // Initialize the FirebaseUI Widget using Firebase.
var ui = new firebaseui.auth.GoogleAuthProvider(auth);
function Signup() {
const firebaseUiConfig = {
signInFlow: 'popup',
signInSuccessUrl: '/',
tosUrl: '/terms-of-service',
privacyPolicyUrl: '/privacy-policy',
signInOptions: [
GoogleAuthProvider.PROVIDER_ID
]
}
return (
<div>
<NavBar />
<StyledFirebaseAuth uiConfig={firebaseUiConfig} firebaseAuth={auth} />
</div>
)
}
export default Signup
Thanks a lot in advance for your help, I don't understand what's going on :(
// EDIT //
I understand it has to deal with SSR. So I did try to dynamically import firebaseUi with next/dynamic. I don't get the error any longer but the page is now blank (just the navbar component renders). Is it because I am passing props inappropriately ?
import dynamic from "next/dynamic";
import { NavBar } from '../components';
import { auth } from '../firebase/initFirebase';
import { GoogleAuthProvider } from 'firebase/auth';
const AuthComponent = dynamic(() =>
import('react-firebaseui/StyledFirebaseAuth').then((mod) => mod.StyledFirebaseAuth)
)
function Signup() {
const firebaseUiConfig = {
// signInFlow: 'popup',
signInSuccessUrl: '/',
tosUrl: '/legal',
privacyPolicyUrl: '/legal',
signInOptions: [
GoogleAuthProvider.PROVIDER_ID
]
}
return (
<div>
<NavBar />
<AuthComponent uiConfig={firebaseUiConfig} firebaseAuth={auth} />
</div>
)
}
export default Signup
The idea here to disable SSR on the page which used firebaseui.
This can be done in two steps.
Use firebase ui or any library which needs window keywork to work.
import React from 'react';
import Modal from '#leafygreen-ui/modal';
import * as firebaseui from 'firebaseui'
import 'firebaseui/dist/firebaseui.css'
export default function AuthUi({open, setOpen}) {
return (
<>
<Modal open={open} setOpen={setOpen}>
// Modal Content goes here.
// Signup widgets comes here
</Modal>
</>
);
}
while importing the library, do something like this.
//__app.js
// import AuthUi from '../components/authUi'; >> Replace this by code below
import dynamic from 'next/dynamic'
const AuthUi = dynamic(
() => import('../components/authUi'),
{ ssr: false }
);
Now you would be able to use firebaseui without window error.

React native persist and encrypt user token - Redux-persist-transform-encrypt error

It seems there is an issue using the encrypt option of redux-persist in react-native:
https://github.com/maxdeviant/redux-persist-transform-encrypt/issues/15
Can anyone help with any solution/workaround to use redux persist to encrypt and store a login token in react-native?
When I try to use the redux persist with the redux-persist-transform-encrypt i get
Redux-persist-transform-encrypt: expected outbound state to be a string error
import { createStore, compose, applyMiddleware } from 'redux';
import ReduxThunk from 'redux-thunk';
import { persistStore, autoRehydrate } from 'redux-persist';
import { AsyncStorage } from 'react-native';
import createEncryptor from 'redux-persist-transform-encrypt';
import reducers from './reducers';
const store = createStore(
reducers,
{},
compose(
applyMiddleware(ReduxThunk),
autoRehydrate(),
),
);
const encryptor = createEncryptor({
secretKey: 'my-super-secret-key-999',
});
persistStore(
store,
{
storage: AsyncStorage,
whitelist: ['auth'],
transforms: [encryptor],
},
);
export default store;
My auth state is something like this:
const INITIAL_STATE = {
user: null,
token: ''
};
Is there any solution to use redux-persist-transform encrypt or the transform and other package to encrypt the token when using redux persist?
I found a solution using the customTransform instead of redux-persist-transform-encrypt:
import { createStore, compose, applyMiddleware } from 'redux';
import ReduxThunk from 'redux-thunk';
import { persistStore, createTransform, autoRehydrate } from 'redux-persist';
import { AsyncStorage } from 'react-native';
import CryptoJS from 'crypto-js';
import reducers from './reducers';
const store = createStore(
reducers,
{},
compose(
applyMiddleware(ReduxThunk),
autoRehydrate(),
),
);
const encrypt = createTransform(
(inboundState, key) => {
if (!inboundState) return inboundState;
const cryptedText = CryptoJS.AES.encrypt(JSON.stringify(inboundState), 'secret key 123');
return cryptedText.toString();
},
(outboundState, key) => {
if (!outboundState) return outboundState;
const bytes = CryptoJS.AES.decrypt(outboundState, 'secret key 123');
const decrypted = bytes.toString(CryptoJS.enc.Utf8);
return JSON.parse(decrypted);
},
);
persistStore(
store,
{
storage: AsyncStorage,
whitelist: ['auth'], // <-- keys from state that should be persisted
transforms: [encrypt],
},
);
export default store;
When using redux-persist initial state is triggered before rehydrating is finished so I had to apply this too:
https://github.com/rt2zz/redux-persist/blob/master/docs/recipes.md#delay-render-until-rehydration-complete
This worked for me:
import { createStore } from 'redux';
import { persistStore, persistReducer } from 'redux-persist';
import createEncryptor from 'redux-persist-transform-encrypt';
import storage from 'redux-persist/lib/storage';
import rootReducer from '/path/to/your/rootReducer';
const encryptor = createEncryptor({
secretKey: 'omg-this-is-some-secret-stuff',
});
const persistConfig = {
key: 'root',
storage,
transforms: [encryptor],
};
const reducer = persistReducer(persistConfig, rootReducer);
export const store = createStore(reducer);
export const persistor = persistStore(store);
This is working fine and store data in session storage.
Use below to encript redux data.
1) install redux-persist-transform-encrypt module
yarn add redux-persist-transform-encrypt
npm install redux-persist-transform-encrypt --save
2) import redux files.
import { createStore } from 'redux';
import { persistStore, persistReducer } from 'redux-persist';
import createEncryptor from 'redux-persist-transform-encrypt';
import storageSession from 'redux-persist/lib/storage/session';// store data in session storage
// import storage from 'redux-persist/lib/storage'; // store data in local storage
import promise from 'redux-promise';
import rootReducer from './path/reducers/';
const encryptor = createEncryptor({
secretKey: 'test#key12',
});
const persistConfig = {
key: 'root',
storage:storageSession,
// storage:storage,
transforms: [encryptor],
}
const persistedReducer = persistReducer(persistConfig, rootReducer)
export default () => {
let store = createStore(persistedReducer)
let persistor = persistStore(store)
return { store, persistor }
}

Resources