How to view the data stored in redux orm by a reducer in another file? - redux

I have redux and redux-orm integrated to my async store of react-native, expo app.
I have defined my model like this.
model.js
import { Model, attr, many, ORM, fk } from "redux-orm";
export class Zuser extends Model {
static modelName = "Zuser";
static fields = {
id: attr(),
firstName: attr(),
lastName: attr(),
};
}
Regestiring it in
orm.js
import { ORM } from "redux-orm";
import { Zuser } from "./model";
const orm = new ORM();
orm.register(Zuser);
export { orm };
Configured the orm in
store.js
import { configureStore } from "#reduxjs/toolkit";
import thunk from "redux-thunk";
import AsyncStorage from "#react-native-async-storage/async-storage";
import appReducer from "../slices/app.slice";
import ormReducer from "../slices/orm.slice";
import { persistReducer } from "redux-persist";
/*
the configureStore from "#reduxjs/toolkit" to create the store and persist the store.
It will automatically apply the middleware and other enhancers, so you don't need to call applyMiddleware separately.
*/
const persistConfig = {
key: "root",
storage: AsyncStorage,
whitelist: ["app", "orm"],
};
const rootReducer = {
app: persistReducer(persistConfig, appReducer),
orm: persistReducer(persistConfig, ormReducer),
};
const store = configureStore({
reducer: rootReducer,
middleware: [thunk],
});
export default store;
Making the store persist in
persistor.js
import { persistStore } from "redux-persist";
import store from "./store";
export const persistor = persistStore(store);
I have configured the above in
app.js
<Provider store={store}>
<PersistGate loading={null} persistor={persistor}>
<Navigator linking={linking} notificationChange={notificationChange} />
</PersistGate>
</Provider>
I have created reducer and selector for storing and retriving zuser data in
orm.slice.js
import { createSlice, createAsyncThunk } from "#reduxjs/toolkit";
import { orm } from "../../common/orm";
import { createSelector } from "#reduxjs/toolkit";
export const fetchZuser = createAsyncThunk("items/fetchZuser", async (uid) => {
const response = await fetch(
`https://XYZ/zen/get_zuser/${uid}`
);
const resp = await response.json();
if ((await resp.success) === false)
console.log("Error at: fetchZuser(), Problem while fetching zuser");
return await resp.data[0];
// Gives {id, firstName, lastName}
});
const ormSlice = createSlice({
name: "items",
initialState: { orm: orm.getEmptyState() },
reducers: {},
extraReducers: (builder) => {
builder.addCase(fetchZuser.fulfilled, (state, action) => {
const session = orm.mutableSession(state.orm);
const Zuser = session.Zuser;
const { objectId, firstName, lastName } = action.payload;
console.log("**Objects to store** ", action.payload);
Zuser.create({ id: objectId, firstName, lastName });
console.log("**Stored objects** ", Zuser.all().toModelArray());
state.orm = session.state;
});
},
});
const selectOrm = (state) => state.orm;
export const selectZuser = createSelector([selectOrm], (ormState) => {
const session = orm.session(ormState);
const Zuser = session.Zuser;
console.log("**Selector Zuser Session** ", Zuser);
let zobjects = Zuser.all().toRefArray()
console.log("**Selector zuser objects** ", zobjects);
});
export const {} = ormSlice.actions;
export default ormSlice.reducer;
I am calling the dispatch reducer thunk in
login.js
var res = dispatch(fetchZuser("1ZkDGFs8sX"));
console.log("Login res ", res);
It says the data is stored.
console
LOG **Objects to store** {"createdAt": "2022-12-13T07:01:01.591Z", "firstName": "oonga", "lastName": "boonga", "objectId": "NVlGiiw8Po", "updatedAt": "2023-02-05T08:54:58.723Z", "userPointer": {"__type": "Pointer", "className": "_User", "objectId": "1ZkDGFs8sX"}}
LOG **Stored objects** [{"_fields": {"firstName": "oonga", "id": "NVlGiiw8Po", "lastName": "boonga"}}]
Next when I try to use the selectZuser selector in
home.js
const zusers = useSelector(selectZuser);
console.log("Home zusers selector ", zusers);
I cant find any data, infact it gives me error in the selector.
console
LOG Selector Zuser Session [Function SessionBoundModel]
ERROR TypeError: undefined is not an object (evaluating 'branch[this.arrName]')
Package.json
{
"name": "timely-reflection",
"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": {
"#expo/metro-config": "^0.3.22",
"#parse/react-native": "^0.0.1-alpha.17",
"#react-native-async-storage/async-storage": "~1.15.0",
"#react-navigation/bottom-tabs": "^5.11.2",
"#react-navigation/native": "^5.8.10",
"#react-navigation/native-stack": "^6.9.1",
"#react-navigation/stack": "^5.12.8",
"#reduxjs/toolkit": "^1.8.6",
"accordion-collapse-react-native": "^1.1.1",
"deep-equal": "^2.0.5",
"expo": "^47.0.0",
"expo-app-loading": "^2.1.0",
"expo-auth-session": "~3.6.1",
"expo-device": "^4.3.0",
"expo-notifications": "^0.16.1",
"expo-random": "~12.2.0",
"expo-splash-screen": "^0.16.2",
"expo-web-browser": "~10.0.3",
"inline-css": "^4.0.1",
"inline-scripts": "^1.7.4",
"moment": "^2.29.4",
"moment-timezone": "^0.5.37",
"parse": "3.4.0",
"prop-types": "^15.8.1",
"react": "17.0.2",
"react-dom": "17.0.2",
"react-native": "0.68.2",
"react-native-collapsible-tab-view": "^4.5.2",
"react-native-dropdown-picker": "^5.4.2",
"react-native-gesture-handler": "~2.8.0",
"react-native-reanimated": "^2.10.0",
"react-native-safe-area-context": "^4.3.4",
"react-native-screens": "^3.17.0",
"react-native-sha1": "^1.2.3",
"react-native-uuid": "^2.0.1",
"react-native-web": "0.17.7",
"react-native-webview": "^11.23.0",
"react-redux": "^8.0.4",
"redux-orm": "^0.16.2",
"redux-persist": "^6.0.0",
"redux-thunk": "^2.4.1"
},
"devDependencies": {
"#babel/core": "^7.19.3"
},
"private": true
}
I tried persisting the store.
I am trying mutable session instead after normal session not working.
I am expecting to see the data stored when login happens in the home page.

Related

Apollo Client is not working with NextJS using SSR

I'm trying to use Apollo Client/Server for my NextJS, and some pages I'm trying to SSR and staticlly generate them, but I'm faing an issue with Apollo where it fails to fetch on server but not when I use the client on the client.
Firstlly this is my package json, where my libs are configed:
{
"name": "landing",
"version": "1.0.0",
"private": true,
"scripts": {
"dev": "next dev -p 9999",
"build": "next build",
"start": "next start -p 9999",
"lint": "next lint"
},
"dependencies": {
"#apollo/react-hooks": "^4.0.0",
"#reduxjs/toolkit": "^1.9.0",
"apollo-server-micro": "2.25.1",
"deepmerge": "^4.2.2",
"firebase": "^9.14.0",
"graphql": "^15.5.1",
"loadash": "^1.0.0",
"luxon": "^3.1.1",
"mongoose": "^5.13.15",
"next": "11.0.1",
"next-redux-wrapper": "^8.0.0",
"react": "17.0.2",
"react-dom": "17.0.2",
"react-images-uploading": "^3.1.7",
"react-infinite-scroll-component": "^6.1.0",
"react-redux": "^8.0.5",
"react-tag-input-component": "^2.0.2",
"uuid": "^9.0.0"
},
"devDependencies": {
"autoprefixer": "^10.4.13",
"eslint": "7.32.0",
"eslint-config-next": "11.0.1",
"postcss": "^8.4.19"
}
}
And here is my single API route in pages/api.jsx folder:
import { Connect } from "../utils/Connect";
import { ApolloServer, makeExecutableSchema } from "apollo-server-micro";
import { defs as typeDefs } from "../graphql/defs";
import { resolves as resolvers } from "../graphql/resolves";
Connect();
export const schema = makeExecutableSchema({ typeDefs, resolvers });
const api = { bodyParser: false };
const path = { path: "/api" };
export const config = { api };
export default new ApolloServer({ schema }).createHandler(path);
While this is my Mongo Connection that I imported earlier:
import mongoose from "mongoose";
export const Connect = async () => {
try {
await mongoose.connect(process.env.MONGO_URI, {
useNewUrlParser: true,
useUnifiedTopology: true,
useFindAndModify: false,
useCreateIndex: true,
});
} catch (err) {
console.log(`Something went wrong trying to connect to the database);
process.exit(1);
}
};
While this is my Apollo Client which is configured for Client and Server calls:
import merge from "deepmerge";
import { useMemo } from "react";
import { ApolloClient, HttpLink, InMemoryCache, from } from "#apollo/client";
import { onError } from "#apollo/client/link/error";
import { concatPagination } from "#apollo/client/utilities";
import { isEqual } from "lodash";
export const APOLLO_STATE_PROP_NAME = "__APOLLO_STATE__";
let apolloClient;
const errorLink = onError(({ graphQLErrors, networkError }) => {
if (graphQLErrors) graphQLErrors.forEach(({ message, locations, path }) => {
const msg = `[GraphQL error]: Message: ${message}`;
const lct = `Location: ${locations}`;
const pth = `Path: ${path}`;
console.log(`${msg}, ${lct}, ${pth}`);
});
if (networkError) {
const ntw = `[Network error]: ${networkError}`;
console.log(ntw);
}
});
const httpLink = new HttpLink({
uri: `http://localhost:9999/api`,
credentials: "same-origin",
});
function createApolloClient() {
return new ApolloClient({
ssrMode: typeof window === "undefined",
link: from([errorLink, httpLink]),
cache: new InMemoryCache({
typePolicies: {
Query: {
fields: {
allPosts: concatPagination(),
},
},
},
}),
});
}
export function initializeApollo(initialState = null) {
const _apolloClient = apolloClient ?? createApolloClient();
if (initialState) {
const existingCache = _apolloClient.extract();
const data = merge(existingCache, initialState, {
arrayMerge: (destinationArray, sourceArray) => [
...sourceArray,
...destinationArray.filter((d) =>
sourceArray.every((s) => !isEqual(d, s))
),
],
});
_apolloClient.cache.restore(data);
}
if (typeof window === "undefined") return _apolloClient;
if (!apolloClient) apolloClient = _apolloClient;
return _apolloClient;
}
export function addApolloState(client, pageProps) {
if (pageProps?.props) pageProps.props[APOLLO_STATE_PROP_NAME] = client.cache.extract();
return pageProps;
}
export function useApollo(pageProps) {
const state = pageProps[APOLLO_STATE_PROP_NAME];
const store = useMemo(() => initializeApollo(state), [state]);
return store;
}
And lately, this is my page that is SSR-ing:
import { Category } from "../../ui/pages";
import { addApolloState, initializeApollo } from "../../config/Apollo";
import { Description, Globals, Title } from "../../config/Metas";
import { CATEGORIES, CATEGORY } from "../../graphql/queries";
export async function getStaticPaths() {
let paths = [];
const Apollo = initializeApollo();
const config = { query: CATEGORIES };
const categories = await Apollo.query(config);
paths = categories.data.Categories.map((category) => {
return {
params: {
category: category.Name.toLowerCase(),
...category,
},
};
});
return {
paths,
fallback: false,
};
}
export async function getStaticProps(context) {
const Apollo = initializeApollo();
const slug = context.params.category;
const category = await Apollo.query({
query: CATEGORY,
variables: { slug },
});
if (category) {
const data = { props: { category } };
return addApolloState(Apollo, data);
}
else return {
notFound: true,
};
}
const Route = ({ category }) => {
const { data } = category;
const { Category: Meta } = data;
return (
<>
<Globals />
<Title title={Meta.Name} />
<Description description={Meta.Description} />
<Category />
</>
);
};
export default Route;
All those queries that I call are being tested on the Apollo client on front and they are working, but when I do this and start the server with npm run dev I get a weird error:
[Network error]: TypeError: fetch failed
Error [ApolloError]: fetch failed
at new ApolloError (/Users/bfzli/Code/landdding/node_modules/#apollo/client/errors/errors.cjs:34:28)
at /Users/bf/Code/landing/node_modules/#apollo/client/core/core.cjs:1800:19
at both (/Users/bf/Code/landing/node_modules/#apollo/client/utilities/utilities.cjs:997:53)
at /Users/bf/Code/landing/node_modules/#apollo/client/utilities/utilities.cjs:990:72
at new Promise (<anonymous>)
at Object.then (/Users/bf/Code/landing/node_modules/#apollo/client/utilities/utilities.cjs:990:24)
at Object.error (/Users/bf/Code/landing/node_modules/#apollo/client/utilities/utilities.cjs:998:49)
at notifySubscription (/Users/bf/Code/landing/node_modules/zen-observable/lib/Observable.js:140:18)
at onNotify (/Users/bf/Code/landing/node_modules/zen-observable/lib/Observable.js:179:3)
at SubscriptionObserver.error (/Users/bf/Code/landing/node_modules/zen-observable/lib/Observable.js:240:7) {
type: 'ApolloError',
graphQLErrors: [],
clientErrors: [],
networkError: {
cause: {
errno: -61,
code: 'ECONNREFUSED',
syscall: 'connect',
address: '::1',
port: 9999
}
}
}

DeepLinking with RN Firebase Messaging / React Navigation from quit state not working

Expected Behavior: User gets a notification via Firebase -> User Taps on notification -> app opens up and goes to correct page.
Actual Behavior: When the user taps on the notification (while App is in quit state), the app opens up normally
I've gotten this to work for when the app is in the background, but not when the app is in the quit state (user has swiped it away). I don't know why this isn't working.
I'm using RN Firebase for the notifications, React Navigation for navigating
to start off with, here are the packages used
// client Package.json
"dependencies": {
"#react-native-async-storage/async-storage": "^1.15.9",
"#react-native-community/masked-view": "^0.1.11",
"#react-native-firebase/analytics": "^14.3.2",
"#react-native-firebase/app": "^14.3.2",
"#react-native-firebase/messaging": "^14.3.2",
"#react-navigation/bottom-tabs": "^6.3.3",
"#react-navigation/native": "^6.0.8",
"#react-navigation/native-stack": "^6.5.0",
"#reduxjs/toolkit": "^1.8.5",
"#trpc/client": "^9.16.0",
"babel-plugin-inline-import": "^3.0.0",
"native-base": "^3.0.7",
"app-symlink-folder": "file:../common",
"react": "17.0.2",
"react-error-boundary": "^3.1.4",
"react-native": "0.66.1",
"react-native-async-storage": "^0.0.1",
"react-native-autogrow-textinput": "^5.4.0",
"react-native-confirmation-code-field": "^7.3.0",
"react-native-date-picker": "^4.0.0",
"react-native-drag-sort": "^2.4.4",
"react-native-geolocation-service": "^5.3.0-beta.4",
"react-native-gesture-handler": "^2.2.0",
"react-native-image-crop-picker": "^0.36.2",
"react-native-keyboard-aware-scroll-view": "^0.9.5",
"react-native-keyboard-spacer": "^0.4.1",
"react-native-keychain": "^8.1.0",
"react-native-linear-gradient": "^2.5.6",
"react-native-permissions": "^3.2.0",
"react-native-reanimated": "^2.4.1",
"react-native-safe-area-context": "^3.4.0",
"react-native-screens": "^3.12.0",
"react-native-size-matters": "^0.4.0",
"react-native-svg": "^12.1.1",
"react-native-vector-icons": "^8.1.0",
"react-native-webview": "^11.15.0",
"react-redux": "^7.2.4",
"redux": "^4.1.0",
"redux-logger": "^3.0.6",
"redux-thunk": "^2.3.0",
"rn-swipe-button": "^1.3.7",
"styled-components": "^5.3.0",
"styled-system": "^5.1.5",
"zod": "3.19.0"
}
// backend package.json
"dependencies": {
"#googlemaps/google-maps-services-js": "^3.3.8",
"#trpc/client": "^9.16.0",
"#trpc/server": "^9.16.0",
"dotenv-safe": "^8.2.0",
"express": "^4.17.1",
"firebase-admin": "^11.0.1",
"firebase-tools": "^11.8.1",
"jsonwebtoken": "^8.5.1",
"morgan": "^1.10.0",
"multer": "^1.4.4",
"node-fetch": "^2.6.1",
"pg": "^8.6.0",
"pg-format": "^1.0.4",
"app-symlinked-folder": "link:../common",
"sharp": "^0.30.6",
"shuffle-array": "^1.0.1",
"twilio": "^3.71.1",
"zod": "3.19.0"
},
Here is the Notification Object being sent
// firebaseMessaging
const firebaseResults = await admin.messaging().sendToDevice(fcm, {
data: {
type: "MESSAGE",
url: 'myApp://app/screen1'
} as notification.NotificationData,
notification: {
title: 'title',
body: 'body'
},
},{
contentAvailable: true
});
Here's the app entry point
// index.js
import React, { useEffect } from 'react';
import {AppRegistry} from 'react-native';
import App from './src/App';
import {name as appName} from './app.json';
import fcm from '#react-native-firebase/messaging';
import * as notificationTypes from 'app-symlink-folder/notification'
import { Linking } from 'react-native';
fcm().setBackgroundMessageHandler(async(message) => {
const parsedData = notificationTypes.notificationData.parse(message.data);
if (parsedData.url) {
// ** Note ** this openURL method isn't working. Some console logs have shown that it's being reached when the user opens the notification from the quit state
await Linking.openURL(parsedData.url)
}
})
const FakeApp = () => {
useEffect(()=> {
console.log('inside fake app')
},[])
return null
}
function HeadlessCheck({isHeadless}) {
fcm().getIsHeadless().then((fcmHeadless)=> {
console.log('headless status', isHeadless, fcmHeadless)
if (isHeadless || fcmHeadless) return <FakeApp />
})
return <App />
}
// Note: I've found some SO and git threads suggesting to do this. I don't think it's really made any difference since I've been working on IOS. I think this is for Android.
AppRegistry.registerComponent(appName, () => HeadlessCheck);
App.tsx is mostly just containers and providers
// App.tsx
export default function App() {
return (
<Providers and containers>
<RootNavigation />
</ ...>
)
}
Here is the root navigator, that handles directing everything
const RootNavigator = () => {
const config:LinkingOptions<RootStackParamList>['config'] = {
screens: {
CHAT: {
path: `chat/:otherUserId/:channelId/`,
parse: {
otherUserId: (otherUserId:string) => `${otherUserId}`,
channelId: (channelId:string) => `${channelId}`,
}
},
APP: {
path: 'app/',
screens: {
'SCREEN1': "screen1/",
'SCREEN2': "screen2/"
}
},
HOMEPAGE: HOMEPAGE,
NOTFOUND: '*'
}
}
// linking used for React Navigation deep linking
const linking:LinkingOptions<RootStackParamList> = {
// url scheme
prefixes: ['myApp://'],
config
}
useEffect(()=> {
const unsubscribe = fcm().onNotificationOpenedApp((message) => {
const parsedData = notificationTypes.notificationData.parse(message.data);
if (parsedData.url) {
Linking.openURL(parsedData.url)
}
})
return unsubscribe
},[])
// app navigator
const AppNavigator = () => {
useEffect(() => {
// cleanup function for fcm
const unsubscribeFCM = fcm().onMessage(async remoteMessage => {
const parsedData = notificationTypes.notificationData.parse(
remoteMessage.data,
);
// do stuff with parsedData
return unsubscribeFCM
});
// set up permissions for fcm
(async () => {
fcm()
.hasPermission()
.then(status => {
if (status !== fcm.AuthorizationStatus.AUTHORIZED) {
fcm()
.requestPermission()
.catch(e => {
// handle error
});
}
});
})();
return unsubscribeFCM;
}, []);
return (
<Tab.Navigator>
<Stack.Screen name={SCREEN1} component={Screen1} />
<Stack.Screen name={SCREEN2} component={Screen2} />
</Tab.Navigator>
)
}
return (
<NavigationContainer
linking={linking}
fallback={<FallBack />}
ref={navigationRef}
onReady={persistantLoginThunk()}
/>
<Stack.Navigator>
<Stack.Screen name={HOMEPAGE} component={HomePage} />
<Stack.Screen name={CHAT} component={Chat} />
<Stack.Screen name={APP} component={AppNavigator} />
</Stack.Navigator>
)
}
You should use:
getInitialNotification: When the application is opened from a quit state.
onNotificationOpenedApp: When the application is running, but in the background.
instead of setBackgroundMessageHandler
See https://rnfirebase.io/messaging/notifications#handling-interaction

React Admin, Next.js, Redux configuration

I added react-admin to an existing project using redux, following these instructions
https://marmelab.com/blog/2022/02/02/bootstrap-your-react-admin-project-with-nextjs.html
But unfortunately the /admin page did not work because I already had redux built into the project. Then I started to follow this instruction:
https://marmelab.com/react-admin/CustomApp.html
I created a store for the admin
import { applyMiddleware, combineReducers, compose, createStore } from "redux";
import { routerMiddleware, connectRouter } from "connected-react-router";
import createSagaMiddleware from "redux-saga";
import { all, fork } from "redux-saga/effects";
import { adminReducer, adminSaga, USER_LOGOUT } from "react-admin";
import { reducerMain, defaultState } from "./store";
export default ({ authProvider, dataProvider, history }) => {
const reducer = combineReducers({
admin: adminReducer,
router: connectRouter(history),
state: reducerMain, // my reducer
});
const resettableAppReducer = (state, action) =>
reducer(action.type !== USER_LOGOUT ? state : undefined, action);
const saga = function* rootSaga() {
yield all(
[
adminSaga(dataProvider, authProvider),
// add your own sagas here
].map(fork)
);
};
const sagaMiddleware = createSagaMiddleware();
const composeEnhancers =
(process.env.NODE_ENV === "development" &&
typeof window !== "undefined" &&
window.__REDUX_DEVTOOLS_EXTENSION_COMPOSE__ &&
window.__REDUX_DEVTOOLS_EXTENSION_COMPOSE__({
trace: true,
traceLimit: 25,
})) ||
compose;
const store = createStore(
resettableAppReducer,
{
state: defaultState, //my state
},
composeEnhancers(
applyMiddleware(
sagaMiddleware,
routerMiddleware(history)
// add your own middlewares here
)
// add your own enhancers here
)
);
sagaMiddleware.run(saga);
return store;
};
Rewrite _app.js file
import * as React from 'react';
import Head from 'next/head';
import { ThemeProvider } from '#mui/material/styles';
import CssBaseline from '#mui/material/CssBaseline';
import theme from '../theme/theme';
import {Provider} from 'react-redux';
// import store from '../redux/adminStore.js'
import '../styles/style.scss'
//import 'animate.css';
import createAdminStore from '../redux/adminStore'
import {createBrowserHistory as createHistory} from 'history'
import jsonServerProvider from 'ra-data-json-server';
const authProvider = () => Promise.resolve();
const dataProvider = jsonServerProvider('https://jsonplaceholder.typicode.com');
function App({ Component, pageProps }) {
const history = createHistory()
React.useEffect(() => {
const jssStyles = document.querySelector('#jss-server-side');
if (jssStyles) {
jssStyles.parentElement.removeChild(jssStyles);
}
}, []);
return (
<ThemeProvider theme={theme}>
<Provider store={createAdminStore({
authProvider,
dataProvider,
history,
})}>
<Head>
<title>Test</title>
<meta name="viewport" content="initial-scale=1, width=device-width" />
</Head>
<CssBaseline />
<Component {...pageProps} />
</Provider>
</ThemeProvider>
);
}
App.getInitialProps = async ({ Component, ctx }) => ({
pageProps: {
...(Component.getInitialProps ? await Component.getInitialProps(ctx) : {}),
pathname: ctx.pathname,
},
});
export default App;
admin/App.js file:
import * as React from "react";
import { Admin, Resource, ListGuesser } from "react-admin";
import jsonServerProvider from "ra-data-json-server";
import {createBrowserHistory as createHistory} from 'history'
const dataProvider = jsonServerProvider("https://jsonplaceholder.typicode.com");
const App = () => {
const history = createHistory()
return (
<Admin dataProvider={dataProvider} title="My Admin" history={history}>
<Resource name="users" list={ListGuesser} />
<Resource name="posts" list={ListGuesser} />
</Admin>
);
};
export default App;
The project builds, but there is a problem with the history method, if you put it outside the component as shown in the instructions, the project stops building with the same error
Error: Invariant failed
at invariant (...\node_modules\tiny-invariant\dist\tiny-invariant.cjs.js:10:15)
at createBrowserHistory (...\node_modules\history\cjs\history.min.js:1:3677)
at App (...\.next\server\pages\_app.js:154:78)
at d (...\node_modules\react-dom\cjs\react-dom-server.node.production.min.js:33:498)
at bb (...\node_modules\react-dom\cjs\react-dom-server.node.production.min.js:36:16)
at a.b.render (...\node_modules\react-dom\cjs\react-dom-server.node.production.min.js:42:43)
at a.b.read (...\node_modules\react-dom\cjs\react-dom-server.node.production.min.js:41:83)
at Object.exports.renderToString (...\next-admin\node_modules\react-dom\cjs\react-dom-server.node.production.min.js:52:138)
at renderPage (...\next-admin\node_modules\next\dist\server\render.js:768:45)
at Object.ctx.renderPage (...\next-admin\.next\server\pages\_document.js:50:26)
package.json
"dependencies": {
"#emotion/cache": "^11.7.1",
"#emotion/css": "^11.7.1",
"#emotion/react": "^11.8.2",
"#emotion/server": "^11.4.0",
"#emotion/styled": "^11.8.1",
"#mui/icons-material": "^5.0.0-rc.1",
"#mui/material": "^5.0.0-rc.1",
"#mui/styled-engine-sc": "^5.5.2",
"#mui/styles": "^5.5.1",
"#reduxjs/toolkit": "^1.8.0",
"#svgr/webpack": "^6.2.1",
"animate.css": "^4.1.1",
"babel-plugin-transform-imports": "^2.0.0",
"babel-preset-next": "^1.4.0",
"classnames": "^2.3.1",
"connected-react-router": "^6.9.2",
"framer-motion": "^6.2.8",
"next": "^12.1.0",
"next-redux-wrapper": "^7.0.5",
"prop-types": "^15.8.1",
"ra-data-json-server": "^3.19.10",
"react": "^17.0.2",
"react-admin": "^3.19.10",
"react-animated-css": "^1.2.1",
"react-animations": "^1.0.0",
"react-countup": "^6.1.1",
"react-customizable-progressbar": "^1.0.3",
"react-dom": "^17.0.2",
"react-hook-form": "^7.28.0",
"react-redux": "^7.2.6",
"redux": "^4.1.2",
"redux-saga": "^1.1.3",
"sass": "^1.49.9",
"styled-components": "^5.3.3"
},
"devDependencies": {
"babel-plugin-import": "^1.13.3",
"babel-plugin-inline-react-svg": "^2.0.1",
"babel-preset-env": "^1.7.0"
}

firebase.database.ServerValue.TIMESTAMP : database is undefined

It's been days and I still can't figure out why firebase.database is undefined.
chat.js file content
const firebase = require('firebase');
require('firebase/database');
exports.sendMessage = (firebaseRtDb, uid, roomPath, message) => firebaseRtDb.ref(`${roomPath}/messages`).push().set({
participant: uid,
date: firebase.database.ServerValue.TIMESTAMP,
message,
});
chat.spec.js extract
const firebase = require('#firebase/testing');
const { sendMessage } = require('./chat');
const getRtDb = async (projectId, databaseName, auth) => {
const app = firebase.initializeTestApp(
{
projectId,
databaseName,
auth,
},
);
const adminApp = firebase.initializeAdminApp({ databaseName });
const adminDb = adminApp.database();
await firebase
.loadDatabaseRules({
databaseName,
rules: JSON.stringify(rules),
});
const db = app.database();
return [db, adminDb];
};
let db = null;
let adminDb = null;
const myUid = 'lul';
beforeEach(async () => {
const [rtDb, rtAdminDb] = await getRtDb('quickChat', 'quickChat', { uid: myUid });
db = rtDb;
adminDb = rtAdminDb;
});
afterEach(async () => adminDb.ref('/').set(null));
it('Can write to chat', async () => {
const roomPath = 'chatsRooms/room1';
await adminDb.ref(roomPath).set({
participants: {
[myUid]: true,
},
});
return firebase.assertSucceeds(sendMessage(db, myUid, roomPath, 'lol'));
});
I tried replacing const firebase = require('firebase'); by onst firebase = require('firebase/app'); and with and without require('firebase/database');.
With code as is in this post, my IDE recognise firebase.database.ServerValue.TIMESTAMP. But Jest test fails.
I started the project using npx degit sveltejs/template my-svelte-project.
Jest output
● Chat › Participants › Can write to chat
TypeError: Cannot read property 'ServerValue' of undefined
4 | exports.sendMessage = (firebaseRtDb, uid, roomPath, message) => firebaseRtDb.ref(`${roomPath}/messages`).push().set({
5 | participant: uid,
> 6 | date: firebase.database.ServerValue.TIMESTAMP,
| ^
7 | message,
8 | });
9 |
at sendMessage (src/lib/chat.js:6:27)
at Object.<anonymous> (src/lib/chat.spec.js:56:38)
package.json
{
"name": "svelte-app",
"version": "1.0.0",
"scripts": {
"build": "rollup -c",
"dev": "rollup -c -w",
"start": "sirv public",
"test": "jest --detectOpenHandles",
"test:watch": "jest --watchAll",
"test:ci": "jest --runInBand"
},
"devDependencies": {
"#firebase/testing": "^0.20.11",
"#rollup/plugin-commonjs": "^16.0.0",
"#rollup/plugin-node-resolve": "^10.0.0",
"eslint": "^7.16.0",
"eslint-config-airbnb-base": "^14.2.1",
"eslint-plugin-import": "^2.22.1",
"eslint-plugin-jest": "^24.1.3",
"eslint-plugin-promise": "^4.2.1",
"jest": "^26.6.3",
"rollup": "^2.3.4",
"rollup-plugin-css-only": "^3.1.0",
"rollup-plugin-livereload": "^2.0.0",
"rollup-plugin-svelte": "^7.0.0",
"rollup-plugin-terser": "^7.0.0",
"svelte": "^3.0.0"
},
"dependencies": {
"firebase": "^8.2.1",
"sirv-cli": "^1.0.0"
}
}
EDIT 1 : forgot to add getRtDb() definition
The dependency #firebase/testing was the cause. It is deprecated and I had to replace it by #firebase/rules-unit-testing.
I also switched to Typescript and made the import as follow:
chat.spec.ts
import * as firebase from '#firebase/rules-unit-testing';
import rules from '../../database.rules.json';
import { sendMessage } from './chat';
chat.ts
import firebase from 'firebase/app';
import 'firebase/database';

Issue with react native project after react-navigation & expo upgrade

I have the issue below after upgrading my react-native application.
My package.json is shown below
{
"name": "react-native-expo-app",
"version": "0.0.0",
"description": "Hello Expo!",
"author": null,
"private": true,
"main": "node_modules/expo/AppEntry.js",
"dependencies": {
"expo": "^25.0.0",
"firebase": "^4.9.1",
"lodash": "^4.17.4",
"moment": "^2.19.2",
"native-base": "^2.3.2",
"react": "16.2.0",
"react-native": "https://github.com/expo/react-native/archive/sdk-25.0.0.tar.gz",
"react-native-chooser": "^1.6.2",
"react-native-datepicker": "^1.6.0",
"react-native-dropdown": "0.0.6",
"react-native-elements": "^0.16.0",
"react-native-ui-kitten": "^3.0.0",
"react-navigation": "^1.0.0",
"react-navigation-redux-helpers": "^1.0.0",
"react-redux": "^5.0.6",
"redux": "^3.7.2",
"redux-persist": "^4.10.2",
"redux-thunk": "^2.2.0"
}
}
The app seems to be processing subsequent pages while loading the first one as the error message is complaining about HomePage, but it should only be rendering WelcomePage. Please see my App.js code below.
const config = {
key: 'primary',
storage: AsyncStorage
};
const HomeNavigator = TabNavigator({
home: {screen: HomePage},
popular: {screen: PopularPage},
search: {screen: SearchPage},
notifications: {screen: NotificationsPage}
}, {
...TabNavigator.Presets.iOSBottomTabs,
});
const RootNavigator = TabNavigator({
welcome: {screen: WelcomePage},
auth: {screen: AuthPage},
signUp: {screen: SignUpPage},
resetPassword: {screen: ResetPasswordPage},
main: {
screen: DrawerNavigator({
home: {
screen: HomeNavigator,
},
profile: {
screen: ProfilePage,
},
following: {
screen: FollowingPage,
},
bookmarks: {
screen: BookmarksPage,
},
contact: {
screen: ContactPage,
},
info: {
screen: InfoPage,
},
conduct: {
screen: ConductPage,
},
login: {
screen: LoginPage,
},
groupProfile: {
screen: GroupProfilePage
}
},
{
contentComponent: SideMenuPage,
drawerWidth: 250
}
)
}
}, {
tabBarPosition: 'bottom',
backBehavior: 'none',
navigationOptions: {
tabBarVisible: false
},
lazy: true
});
const initialState = RootNavigator.router.getStateForAction(RootNavigator.router.getActionForPathAndParams('welcome'));
const navReducer = (state = initialState, action) => {
const nextState = RootNavigator.router.getStateForAction(action, state);
return nextState || state;
};
const appReducer = combineReducers({
nav: navReducer,
auth,
signUp,
resetPasswordReducer,
home,
popular,
rules,
conduct,
profile
}
);
const middleware = createReactNavigationReduxMiddleware(
"welcome",
state => state.nav,
);
const addListener = createReduxBoundAddListener("welcome");
class AppSupport extends React.Component {
render() {
return (
<RootNavigator navigation={addNavigationHelpers({
// dispatch: this.props.dispatch,
state: this.props.nav,
addListener,
})} />
);
}
}
const mapStateToProps = (state) => ({
nav: state.nav
});
const AppWithNavigationState = connect(mapStateToProps)(AppSupport);
const store = createStore(
appReducer,
applyMiddleware(ReduxThunk),
);
export default class App extends React.Component {
state = {isReady: false};
async componentWillMount() {
const config = {
apiKey: “hidden”,
authDomain: "hidden",
databaseURL: "hidden",
projectId: "hidden",
storageBucket: "hidden",
messagingSenderId: "hidden"
};
firebase.initializeApp(config);
this.setState({isReady: true});
}
render() {
if (this.state.isReady) {
return (
<Provider store={store}>
<AppWithNavigationState />
</Provider>
);
} else {
return <Expo.AppLoading/>
}
}
}
See
The error message indicates that there is no current user on line 17 of HomePage.jsx, where you're trying to use currentUser.displayName.
Most likely (you didn't share the relevant code) you have a direct lookup of the current user, something like:
firebase.auth().currentUser.displayName
You'll want to wrap that in an auth state listener:
firebase.auth().onAuthStateChanged(function(user) {
if (user) {
// User is signed in, get its display name.
}
});
This way the code only runs when there actually is a current user. Also see getting the current user in the Firebase docs.

Resources