I already used Firebase on another app recently. But this time I'm getting that error on console.
It's throwing this error on page
ERROR in ./src/Context/AuthContext.jsx 8:0-49
ERROR in ./src/Firebase.js 4:0-45
and this on console
bundle.js:1861 Uncaught Error: Cannot find module 'firebase/app'
at webpackMissingModule (bundle.js:1861:50)
at ./src/Firebase.js (bundle.js:1861:137)
at options.factory (bundle.js:126646:31)
at webpack_require (bundle.js:126092:33)
at fn (bundle.js:126303:21)
at ./src/Context/AuthContext.jsx (bundle.js:1641:67)
at options.factory (bundle.js:126646:31)
at webpack_require (bundle.js:126092:33)
at fn (bundle.js:126303:21)
at ./src/App.js (bundle.js:20:78)
This is my Firebase.js file
// Import the functions you need from the SDKs you need
import { initializeApp } from "firebase/app";
import { getAuth } from "firebase/auth";
import { getFirestore } from "firebase/firestore";
// TODO: Add SDKs for Firebase products that you want to use
// https://firebase.google.com/docs/web/setup#available-libraries
// Your web app's Firebase configuration
const firebaseConfig = {
apiKey: process.env.REACT_APP_FIREBASE_API_KEY,
authDomain: process.env.REACT_APP_FIREBASE_AUTH_DOMAIN,
projectId: process.env.REACT_APP_FIREBASE_PROJECT_ID,
storageBucket: process.env.REACT_APP_FIREBASE_STORAGE_BUCKET,
messagingSenderId: process.env.REACT_APP_FIREBASE_MESSAGING_SENDER,
appId: process.env.REACT_APP_FIREBASE_APP_ID,
};
// Initialize Firebase
const app = initializeApp(firebaseConfig);
export const auth = getAuth(app);
export const db = getFirestore(app);
export default app;
And this provider context file
import { createContext, useContext, useState, useEffect } from "react";
import { auth, db } from "../Firebase";
import { doc, setDoc } from "firebase/firestore";
import {
createUserWithEmailAndPassword,
signInWithEmailAndPassword,
signOut,
onAuthStateChanged,
} from "firebase/auth";
const UserContext = createContext();
export const AuthContextProvider = ({ children }) => {
const [user, setUser] = useState({});
const signUp = (email, password) => {
createUserWithEmailAndPassword(auth, email, password);
return setDoc(doc(db, "users", email), {
favList: [],
});
};
const signIn = (email, password) => {
return signInWithEmailAndPassword(auth, email, password);
};
const logout = () => {
return signOut(auth);
};
useEffect(() => {
const unsubscribe = onAuthStateChanged(auth, (currentUser) => {
setUser(currentUser);
});
return () => {
unsubscribe();
};
}, []);
return (
<UserContext.Provider value={{ signUp, signIn, logout, user }}>
{children}
</UserContext.Provider>
);
};
export const UserAuth = () => {
return useContext(UserContext);
};
package.json
{
"name": "cryptotracker-app",
"version": "0.1.0",
"private": true,
"dependencies": {
"#testing-library/jest-dom": "^5.16.5",
"#testing-library/react": "^13.4.0",
"#testing-library/user-event": "^13.5.0",
"axios": "^1.3.1",
"dompurify": "^2.4.3",
"firebase": "^9.17.0",
"react": "^18.2.0",
"react-dom": "^18.2.0",
"react-icons": "^4.7.1",
"react-router-dom": "^6.8.0",
"react-scripts": "5.0.1",
"react-sparklines": "^1.7.0",
"web-vitals": "^2.1.4"
},
"scripts": {
"start": "react-scripts start",
"build": "react-scripts build",
"test": "react-scripts test",
"eject": "react-scripts eject"
},
"eslintConfig": {
"extends": [
"react-app",
"react-app/jest"
]
},
"browserslist": {
"production": [
">0.2%",
"not dead",
"not op_mini all"
],
"development": [
"last 1 chrome version",
"last 1 firefox version",
"last 1 safari version"
]
},
"devDependencies": {
"tailwindcss": "^3.2.4"
}
}
I tried most of things like uninstall and install but they didn't work.
I am also getting the same error,but after removing the firebase version 9.17.0 and reinstalling firebase with its 9.16.0 vesrion all the error has been resolved.
Latest version of firebase might be unstable.
Related
I am trying to run a test in next.js using jest that imports firebase, but i keep getting an error:
{import { registerVersion } from '#firebase/app'; SyntaxError: Cannot use import statement outside a module
Importing other modules works, but firebase throughs that error. I have tried other enviroments but none seem to work and either throw this error or another error.
Package.JSON:
{
"name": "chat",
"version": "0.1.0",
"private": true,
"scripts": {
"dev": "next dev",
"build": "next build",
"start": "next start",
"lint": "next lint",
"test": "jest --forceExit --watchAll --coverage"
},
"dependencies": {
"#firebase/testing": "^0.20.11",
"firebase": "^9.9.4",
"kill-port": "^2.0.1",
"next": "12.2.5",
"react": "18.2.0",
"react-dom": "18.2.0",
"react-firebase-hooks": "^5.0.3",
"react-hot-toast": "^2.3.0",
"uuid": "^8.3.2"
},
"devDependencies": {
"#babel/plugin-syntax-jsx": "^7.18.6",
"#babel/preset-react": "^7.18.6",
"#firebase/rules-unit-testing": "^2.0.4",
"#testing-library/jest-dom": "^5.16.5",
"#testing-library/react": "^13.4.0",
"#types/jest": "^29.0.2",
"eslint": "8.23.0",
"eslint-config-next": "12.2.5",
"firebase-admin": "^11.0.1",
"jest": "^29.0.3",
"jest-environment-jsdom": "^29.0.3"
}
}
Jest.config.js:
// jest.config.js
const nextJest = require('next/jest');
const createJestConfig = nextJest({
// Provide the path to your Next.js app to load next.config.js and .env files in your test environment
dir: './',
});
// Add any custom config to be passed to Jest
/** #type {import('jest').Config} */
const customJestConfig = {
// Add more setup options before each test is run
// setupFilesAfterEnv: ['<rootDir>/jest.setup.js'],
// if using TypeScript with a baseUrl set to the root directory then you need the below for alias' to work
//moduleDirectories: ['node_modules', '<rootDir>/'],
testEnvironment: 'jest-environment-jsdom',
};
// createJestConfig is exported this way to ensure that next/jest can load the Next.js config which is async
module.exports = createJestConfig(customJestConfig);
test/page.test.js
/**
* #jest-environment jest-environment-jsdom
*/
import React from 'react';
import { render, screen } from '#testing-library/react';
import Thing from '../../pages/thing.jsx';
describe('testing Home page', () => {
test('render h1 element', () => {
expect(render(<Thing />));
});
});
pages/test.jsx
import { firestore } from "../lib/firebase";
export default function Thing({ }) {
return (
<main>
</main>
);
}
lib/firebase (Note: removed config fields)
import { initializeApp } from 'firebase/app';
import { getAuth, GoogleAuthProvider } from 'firebase/auth';
import { getFirestore } from 'firebase/firestore';
import { getStorage } from 'firebase/storage';
const firebaseConfig = {
apiKey: "",
authDomain: "",
projectId: "",
storageBucket: "",
messagingSenderId: "",
appId: "",
measurementId: ""
};
const app = initializeApp(firebaseConfig);
export const auth = getAuth(app);
export const googleAuthProvider = new GoogleAuthProvider();
export const firestore = getFirestore(app);
export const storage = getStorage(app);
I am using the following packages and have installed tailwindcss in the following project folder /home/admin/Desktop/Code/main_project/client/package.json:
{
"name": "react-app",
"version": "1.0",
"private": true,
"dependencies": {
"babel-eslint": "10.0.3",
"react": "^17.0.2",
"react-dom": "^17.0.2",
"react-redux": "^7.2.4",
"react-router": "^6.3.0",
"react-scripts": "3.2.0",
"redux": "^4.1.1",
"redux-thunk": "^2.3.0",
"web-vitals": "^1.0.1",
"web3": "^1.6.1",
"web3-eth-contract": "^1.5.2"
},
"scripts": {
"start": "react-scripts start",
"build": "react-scripts build",
"test": "react-scripts test",
"eject": "react-scripts eject"
},
"eslintConfig": {
"extends": "react-app"
},
"browserslist": {
"production": [
">0.2%",
"not dead",
"not op_mini all"
],
"development": [
"last 1 chrome version",
"last 1 firefox version",
"last 1 safari version"
]
},
"devDependencies": {
"autoprefixer": "^10.4.7",
"postcss": "^8.4.14",
"tailwindcss": "^3.0.24"
}
}
My tailwind.config.js looks like the following:
module.exports = {
content: [
"./src/**/*.{js,jsx,ts,tsx}",
],
theme: {
extend: {},
},
plugins: [],
}
As you can see my react-project lies in a subfolder.
My postcss.config.js looks like the following:
module.exports = {
plugins: {
tailwindcss: {},
autoprefixer: {},
},
}
This is my index.css:
#tailwind base;
#tailwind components;
#tailwind utilities;
In my index.js I am loading my index.css:
import React from 'react';
import ReactDOM from 'react-dom';
import './index.css';
import App from './App';
import * as serviceWorker from './serviceWorker';
import store from "./redux/store";
import { Provider } from "react-redux";
ReactDOM.render(
<Provider store={store}>
<App />
</Provider>,
document.getElementById("root")
);
// If you want your app to work offline and load faster, you can change
// unregister() to register() below. Note this comes with some pitfalls.
serviceWorker.unregister();
My App.js looks like the following:
import React, { useEffect, useState, useRef } from "react";
import { useDispatch, useSelector } from "react-redux";
import { connect } from "./redux/blockchain/blockchainActions";
import { fetchData } from "./redux/data/dataActions";
import "./App.css";
function App() {
const dispatch = useDispatch();
const blockchain = useSelector((state) => state.blockchain);
const data = useSelector((state) => state.data);
const [CONFIG, SET_CONFIG] = useState({
CONTRACT_ADDRESS: "",
SCAN_LINK: "",
NETWORK: {
NAME: "",
SYMBOL: "",
ID: 0,
},
NFT_NAME: "",
SYMBOL: "",
MAX_SUPPLY: 1,
WEI_COST: 0,
DISPLAY_COST: 0,
GAS_LIMIT: 0,
MARKETPLACE: "",
MARKETPLACE_LINK: "",
SHOW_BACKGROUND: false,
});
const getData = () => {
if (blockchain.account !== "" && blockchain.smartContract !== null) {
dispatch(fetchData(blockchain.account));
}
};
const getConfig = async () => {
const configResponse = await fetch("/config/config.json", {
headers: {
"Content-Type": "application/json",
Accept: "application/json",
},
});
const config = await configResponse.json();
SET_CONFIG(config);
};
useEffect(() => {
getConfig();
}, []);
useEffect(() => {
getData();
}, [blockchain.account]);
return (
<>
<h1 className="text-3xl font-bold underline">Welcome</h1>
<>
);
}
export default App;
However, the components in my App.js do not get rendered with tailwindcss.
Any suggestions what I am doing wrong?
I appreciate your replies!
I'm creating a react native app that connects to firebase.
However, when I started my app in slow internet speeds, it took a while to load, and the code showed me that this was due to the wait for the authstate listener being slow on slow connections. On airplane mode, it works fine.
How can I make the app load faster, even with slow internet speeds?
import { getApps, initializeApp } from 'firebase/app';
// import 'firebase/compat/auth'
import { getAuth, createUserWithEmailAndPassword, signInWithEmailAndPassword, onAuthStateChanged, signOut } from "firebase/auth";
// import 'firebase//firestore'
import { getFirestore, collection, addDoc, query, where, getDocs, deleteDoc, doc, setDoc, serverTimestamp } from "firebase/firestore"
import AsyncStorage from '#react-native-async-storage/async-storage';
// TODO: Add SDKs for Firebase products that you want to use
// https://firebase.google.com/docs/web/setup#available-libraries
// Your web app's Firebase configuration
// For Firebase JS SDK v7.20.0 and later, measurementId is optional
const firebaseConfig = {*****
};
// Initialize Firebase
if (!getApps().length) {
console.log('initializing firebase');
const app = initializeApp(firebaseConfig);
}
Packages:
{
"name": "tut3",
"version": "1.0.0",
"main": "node_modules/expo/AppEntry.js",
"scripts": {
"start": "expo start",
"android": "expo start --android",
"ios": "expo start --ios",
"web": "expo start --web",
"eject": "expo eject"
},
"dependencies": {
"#gorhom/bottom-sheet": "^4",
"#react-native-async-storage/async-storage": "^1.17.2",
"#react-native-community/datetimepicker": "4.0.0",
"#react-native-community/google-signin": "^5.0.0",
"#react-native-firebase/app": "^14.7.0",
"#react-native-firebase/auth": "^14.7.0",
"#react-native-google-signin/google-signin": "^7.2.2",
"#react-navigation/bottom-tabs": "^6.2.0",
"#react-navigation/material-bottom-tabs": "^6.1.1",
"#react-navigation/native": "^6.0.8",
"#react-navigation/native-stack": "^6.5.2",
"#react-navigation/stack": "^6.1.1",
"expo": "~44.0.0",
"expo-camera": "^12.1.2",
"expo-fast-image": "^1.1.3",
"expo-file-system": "~13.1.4",
"expo-google-app-auth": "~8.3.0",
"expo-image-picker": "^12.0.2",
"expo-location": "~14.0.1",
"expo-status-bar": "^1.2.0",
"expo-updates": "~0.11.6",
"firebase": "^9.6.10",
"moment": "^2.29.1",
"react": "17.0.1",
"react-dom": "17.0.1",
"react-native": "0.64.3",
"react-native-action-button": "^2.8.5",
"react-native-dropdown-picker": "^5.3.0",
"react-native-gesture-handler": "~2.1.0",
"react-native-gifted-chat": "^0.16.3",
"react-native-image-crop-picker": "^0.37.3",
"react-native-keyboard-aware-scroll-view": "^0.9.5",
"react-native-maps": "0.29.4",
"react-native-onboarding-swiper": "^1.2.0",
"react-native-paper": "^4.12.0",
"react-native-reanimated": "~2.3.1",
"react-native-safe-area-context": "^4.2.4",
"react-native-screens": "^3.13.1",
"react-native-skeleton-placeholder": "^5.0.0",
"react-native-stars": "^1.2.2",
"react-native-vector-icons": "^9.1.0",
"react-native-web": "0.17.1",
"reanimated-bottom-sheet": "^1.0.0-alpha.22",
"shorthash": "^0.0.2",
"styled-components": "^5.3.5"
},
"devDependencies": {
"#babel/core": "^7.12.9"
},
"private": true
}
Here is my routes folder that determines what to show on the app until the app initialization is done:
import React, { useContext, useState, useEffect } from 'react';
import { NavigationContainer } from '#react-navigation/native';
import { auth } from './AuthProvider';
// import 'firebase/compat/auth'
import { getAuth, createUserWithEmailAndPassword, signInWithEmailAndPassword, onAuthStateChanged, signOut } from "firebase/auth";
// import 'firebase//firestore'
import { getFirestore, collection, addDoc, query, where, getDocs, deleteDoc, doc, setDoc } from "firebase/firestore"
import { AuthContext } from './AuthProvider';
import AuthStack from './AuthStack';
import AppStack from './AppStack';
import AsyncStorage from '#react-native-async-storage/async-storage';
const Routes = () => {
const { user, setUser } = useContext(AuthContext);
const [initializing, setInitializing] = useState(true);
const onAuthStateChanges = (user) => {
setUser(user);
if (initializing) setInitializing(false);
console.log(user)
};
useEffect(() => {
const subscriber = onAuthStateChanged(auth, onAuthStateChanges);
return subscriber; // unsubscribe on unmount
}, []);
if (initializing) return null;
return (
<NavigationContainer>
{user ? <AppStack /> : <AuthStack />}
</NavigationContainer>
)
};
export default Routes;
Thanks!
EDIT:
After the suggested answer, this is what I've implemented that seems to be working for me. Idea is if the user was previously logged in and exited the app without logging out, then load the appstack.
const Routes = () => {
const { user, setUser } = useContext(AuthContext);
const [initializing, setInitializing] = useState(true);
const [previousUser, setPreviousUser] = useState(null);
const onAuthStateChanges = (user) => {
setUser(user);
AsyncStorage.setItem('user', JSON.stringify(user));
if (initializing) setInitializing(false);
console.log(user)
};
useEffect(() => {
AsyncStorage.getItem('user').then((value) => {
if (value) {
setPreviousUser(true)
setUser(JSON.parse(value))
}
else {
setPreviousUser(false)
}
})
const subscriber = onAuthStateChanged(auth, onAuthStateChanges);
return subscriber; // unsubscribe on unmount
}, []);
if (initializing && user) return (
<NavigationContainer>
<AppStack />
</NavigationContainer>
)
if (initializing && !user) return (
<NavigationContainer>
<AuthStack />
</NavigationContainer>
)
return (
<NavigationContainer>
{!initializing && user ? <AppStack /> : <AuthStack />}
</NavigationContainer>
)
};
The call to initializeApp is synchronous and doesn't need to call the server, so should run pretty quickly and at a speed unrelated to your internet connection.
But onAuthStateChanged waits for the auth state to be restored, which does require a call to the servers to check whether the user's credentials are still valid (for example, that their account wasn't disabled). On a slow internet connection this may take some time.
Since most of such calls will be successful, a common trick is to assume they will succeed and then course correct if it turns out that assumption was wrong. To implement this, you'll need to store a token value in local storage when the user has successfully signed in, and then use that value to determine your initial navigation instead of waiting for onAuthStateChanged.
Firebaser Michael Bleigh talked about this at Google I/O in this video on Architecting Mobile Web Apps.
I've used this test in the past with a React app without any issues:
import { render, fireEvent, screen, waitFor } from '#testing-library/react'
import { RelatedContent } from '../components/relatedcontent'
import { onValue } from '../components/firebase'
jest.mock('../components/firebase')
test('RelatedContent -> displays related content', async () => {
let fakeData = {
'flex-new-row': 20,
'chronlabs': 25
}
let snapshot = {val: () => fakeData}
onValue.mockImplementation((ref, callback) => {
callback(snapshot)
return jest.fn()
})
render(<RelatedContent numRelated = {5}/>)
await waitFor(() => expect(document.querySelector("a[href='/flex-new-row']")).toBeTruthy())
await waitFor(() => expect(document.querySelector("a[href='/chronlabs']")).toBeTruthy())
})
Now I'm using the same test on a Next.js app, and I'm getting the following error:
TypeError: _firebase.onValue.mockImplementation is not a function
Update
The RelatedContent component looks like:
import React, { useState, useEffect } from 'react'
import { db, onValue, ref } from './firebase'
const RelatedContent = ({ numRelated }) => {
const [related, setRelated] = useState([])
useEffect(() => {
let unsubscribe = onValue(ref(db, `posts/related`), snapshot => {
let _related = Object.keys(snapshot.val())
setRelated(_related)
})
return () => unsubscribe()
}, [])
return(
<div className = 'Related'>
{related.slice(0, numRelated).map((elem, i) =>
<Link href = {elem}>Whatever</Link>
)}
</div>
)
}
export default RelatedContent
And the Firebase component looks like:
import { initializeApp } from 'firebase/app'
import { getDatabase, goOnline, goOffline, limitToLast, onDisconnect, onValue, orderByValue, push, query, ref, remove, runTransaction, update } from 'firebase/database'
const config = { ... }
const app = initializeApp(config)
const db = getDatabase(app)
export { db, dbt, goOnline, goOffline, limitToLast, onDisconnect, onValue, orderByValue, push, query, ref, remove, runTransaction, update }
package.json looks like:
{
"name": "app-next",
"private": true,
"scripts": {
"dev": "next dev",
"build": "next build",
"start": "next start",
"lint": "next lint",
"test": "jest"
},
"dependencies": {
"#primer/octicons-react": "^16.3.0",
"chart.js": "^2.7.2",
"firebase": "^9.6.4",
"gfm": "0.0.1",
"moment": "^2.29.1",
"next": "12.0.8",
"prismjs": "^1.26.0",
"react": "17.0.2",
"react-dom": "17.0.2",
"react-markdown": "^8.0.0",
"rehype-katex": "^6.0.2",
"rehype-raw": "^6.1.1",
"remark-gfm": "^3.0.1",
"remark-math": "^5.1.1"
},
"devDependencies": {
"#testing-library/jest-dom": "^5.16.1",
"#testing-library/react": "^12.1.2",
"eslint": "8.7.0",
"eslint-config-next": "12.0.8",
"eslint-plugin-promise": "^6.0.0",
"jest": "^27.4.7"
}
}
If I place the fake data and the onValue.mockImplementation() function before the test declaration, the test passes correctly.
The problem is that I've several tests with multiple definitions of the fake data, and I need to declare the fake data within every test.
If I do so, I get the error.
My firebase has some problems which the console says firestore is undefined. I think the problem actually comes from my firebaseApp or somewhere but i don't know how to fix it. it'd be kind of you guys to help me! Thank you so much!
This is my firebase.js:
import firebase from 'firebase';
const firebaseApp = firebase.initializeApp[{
apiKey: "<API_KEI>",
authDomain: "<PROJECT_ID>.firebaseapp.com",
projectId: "<PROJECT_ID>",
storageBucket: "<PROJECT_ID>.appspot.com",
messagingSenderId: "<SENDER_ID>",
appId: "<APP_ID>",
measurementId: "<MESURMENT_ID>"
}];
const db = firebaseApp.firestore();
const auth = firebase.auth();
export {
auth,
db
};
This is my SignIn.js:
import React from "react";
import firebase from "firebase";
import {
auth
} from "../firebase.js";
function SignIn() {
function signInWithGoogle() {
const provider = new firebase.auth.GoogleAuthProvider();
auth.signInWithPopup(provider);
}
return ( <
div >
<
button onClick = {
signInWithGoogle
} > Sign in with google < /button>{" "} <
/div>
);
}
This is my App.js:
import React from 'react'
import SignIn from './components/SignIn'
import Chat from './components/Chat'
function App() {
return ( <
div >
<
SignIn / >
<
Chat / >
<
/div>
)
}
export default App
This is my package.json:
{
"name": "image-search",
"version": "0.1.0",
"private": true,
"dependencies": {
"#emotion/react": "^11.4.1",
"#emotion/styled": "^11.3.0",
"#fortawesome/fontawesome-free": "^5.15.4",
"#material-ui/core": "^4.12.3",
"#material-ui/icons": "^4.11.2",
"#mui/icons-material": "^5.0.1",
"#mui/material": "^5.0.1",
"#testing-library/jest-dom": "^5.14.1",
"#testing-library/react": "^11.2.7",
"#testing-library/user-event": "^12.8.3",
"firebase": "^8.10.0",
"font-awesome": "^4.7.0",
"react": "^17.0.2",
"react-dom": "^17.0.2",
"react-firebase-hooks": "^3.0.4",
"react-scripts": "4.0.3",
"uuidv4": "^6.2.12",
"web-vitals": "^1.1.2"
},
"scripts": {
"start": "react-scripts start",
"build": "react-scripts build",
"test": "react-scripts test",
"eject": "react-scripts eject"
},
"eslintConfig": {
"extends": [
"react-app",
"react-app/jest"
]
},
"browserslist": {
"production": [
">0.2%",
"not dead",
"not op_mini all"
],
"development": [
"last 1 chrome version",
"last 1 firefox version",
"last 1 safari version"
]
},
"devDependencies": {
"#babel/preset-react": "^7.14.5"
}
}
You can use latest firebase and check the docs below.
In your code, const db = firebaseApp.firestore();, but latest version use const db = getFirestore(app); to initialize db.
This is a demo from official network.
import { initializeApp } from 'firebase/app';
import { getFirestore, collection, getDocs } from 'firebase/firestore/lite';
// Follow this pattern to import other Firebase services
// import { } from 'firebase/<service>';
// TODO: Replace the following with your app's Firebase project configuration
const firebaseConfig = {
//...
};
const app = initializeApp(firebaseConfig);
const db = getFirestore(app);
// Get a list of cities from your database
async function getCities(db) {
const citiesCol = collection(db, 'cities');
const citySnapshot = await getDocs(citiesCol);
const cityList = citySnapshot.docs.map(doc => doc.data());
return cityList;
}
And find more information in this page firebase