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.
Related
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.
I have been trying for 3 days in row to solve this error
TypeError: firebase_config__WEBPACK_IMPORTED_MODULE_2_.default.auth is not a function
but i coudlnt i have tried everything online but nothing has helped me
here is my config file
import { initializeApp } from "firebase/app";
import "firebase/auth";
const firebaseConfig = {
apiKey: "AIzaSyBoKEW_g0gOwNKkHGMAyhXxC0ESfdsVhKI",
authDomain: "kargoevi-auth.firebaseapp.com",
projectId: "kargoevi-auth",
storageBucket: "kargoevi-auth.appspot.com",
messagingSenderId: "726037811463",
appId: "1:726037811463:web:42d75c7f5c1d1b5b9bf5a2",
measurementId: "G-PJXGLVZ6GQ",
};
// Initialize Firebase
const app = initializeApp(firebaseConfig);
export default app;
and here is the Auth.js file
import React, { useEffect, useState } from "react";
import app from "./firebase-config";
export const AuthContext = React.createContext();
export const AuthProvider = ({ children }) => {
const [currentUser, setCurrentUser] = useState(null);
const [pending, setPending] = useState(true);
useEffect(() => {
app.auth().onAuthStateChanged((user) => {
setCurrentUser(user);
setPending(false);
});
}, []);
if (pending) {
return <>Loading...</>;
}
return (
<AuthContext.Provider
value={{
currentUser,
}}
>
{children}
</AuthContext.Provider>
);
};
my package.json file
"dependencies": {
"#testing-library/jest-dom": "^5.16.4",
"#testing-library/react": "^13.3.0",
"#testing-library/user-event": "^13.5.0",
"bootstrap": "^5.2.0",
"card-validator": "^8.1.1",
"craco-plugin-scoped-css": "^1.1.1",
"firebase": "^9.10.0",
"firebase-admin": "^11.0.1",
"react": "^18.2.0",
"react-bootstrap": "^2.4.0",
"react-credit-cards": "^0.8.3",
"react-dom": "^18.2.0",
"react-hook-form": "^7.34.0",
"react-router-dom": "^5.3.0",
"react-scripts": "^2.1.3",
"react-tabs": "^5.1.0",
"styled-components": "^5.3.6",
"update": "^0.7.4",
"web-vitals": "^2.1.4"
},
so basically, what I'm trying to do is to connect my react project with firebase for authentication
i was following this tutorial online from YouTube
You are using the Firebase Modular SDK that uses a functional syntax and you don't have to import other services as side-effects (import "firebase/auth"). As per Firebase Auth's documentation, you have to use getAuth() function to initialize Auth now. Try refactoring the code as shown now:
// firebase.js
import { initializeApp } from "firebase/app";
import { getAuth } from "firebase/auth";
const firebaseConfig = { ... };
export const auth = getAuth();
Similarly, for other methods like onAuthStateChanged you'll have to update the syntax.
import { onAuthStateChanged } from "firebase/auth"
import { auth } from "../path/to/firebase.js" // <-- replace the path
useEffect(() => {
onAuthStateChanged(auth, (user) => {
setCurrentUser(user);
setPending(false);
});
}, []);
Make sure you are referring to Modular tab in the documentation.
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.
I have a react native app, this error start to show up after I detached from expo to pure react native, I am a beginner I don't have much experience with react-native.
I tried removing node_modules and installing the dependencies with npm install.
I have included package.json and App.js
App screenshot
package.json
{
"scripts": {
"start": "react-native start",
"android": "react-native run-android",
"ios": "react-native run-ios",
"test": "node ./node_modules/jest/bin/jest.js --watchAll"
},
"jest": {
"preset": "react-native"
},
"dependencies": {
"#babel/runtime": "^7.4.3",
"#expo/samples": "2.1.1",
"date-and-time": "^0.6.3",
"expo-core": "^3.0.1",
"expo-file-system": "^4.0.0",
"expo-font-interface": "^3.0.0",
"expo-image-loader-interface": "^3.0.0",
"expo-permissions-interface": "^3.0.0",
"expo-react-native-adapter": "^3.0.1",
"firebase": "^5.7.2",
"native-base": "^2.10.0",
"react": "16.5.0",
"react-native": "0.55.4",
"react-native-animatable": "^1.3.1",
"react-native-button": "^2.3.0",
"react-native-datepicker": "^1.7.2",
"react-native-dropdownalert": "^3.10.0",
"react-native-elements": "^0.19.1",
"react-native-firebase": "^5.2.3",
"react-native-parallax-scroll-view": "^0.21.3",
"react-native-ratings": "^6.3.0",
"react-native-splash-screen": "^3.2.0",
"react-native-status-bar-height": "^2.2.0",
"react-native-unimodules": "^0.2.0",
"react-native-vector-icons": "^6.4.2",
"react-navigation": "^2.18.2",
"scheduler": "^0.13.6"
},
"devDependencies": {
"babel-preset-expo": "^5.0.0",
"jest": "^24.7.1"
},
"private": true
}
App.js
import React from "react";
import { Platform, StatusBar, StyleSheet, View, Text } from "react-native";
import { Icon } from "react-native-elements";
import AppNavigator from "./navigation/AppNavigator";
import MainTabNavigator from "./navigation/MainTabNavigator";
import Firebase from "./Firebase";
import SplashScreen from 'react-native-splash-screen'
export default class App extends React.Component {
constructor(props) {
super(props);
this.state = {
isLoadingComplete: false,
isUserLogged: false,
isAuthenticationReady: false
};
Firebase.auth().onAuthStateChanged(this.onAuthStateChanged);
}
componentDidMount() {
SplashScreen.hide();
}
componentWillUnmount() {
this.onTokenRefreshListener();
this.notificationDisplayedListener();
this.notificationListener();
}
onAuthStateChanged = user => {
this.setState({ isAuthenticationReady: true });
this.setState({ isUserLogged: !!user });
};
render() {
if (
!this.state.isLoadingComplete &&
!this.props.skipLoadingScreen &&
!this.state.isAuthenticationReady
) { return <Text />
/*return (
<AppLoading
startAsync={this._loadResourcesAsync}
onError={this._handleLoadingError}
onFinish={this._handleFinishLoading}
autoHideSplash={true}
/>
);*/
} else {
// As soon as app finishs loading and splash screen hides
// Check if user loggedIn
// Firebase.auth().onAuthStateChanged(user => {
// if (user) {
// this.setState({ isUserLogged: true });
// console.log(user.providerData[0].phoneNumber);
// } else {
// console.log("No user logged in yet!");
// }
// });
return (
<View style={styles.container}>
{Platform.OS === "ios" && <StatusBar barStyle="default" />}
{this.state.isUserLogged ? <MainTabNavigator /> : <AppNavigator />}
</View>
);
}
}
_loadResourcesAsync = async () => {
return Promise.all([
Asset.loadAsync([
require("./assets/images/algeria_flag.png"),
require("./assets/images/login_bg.jpg"),
require("./assets/images/road.jpg")
]),
Font.loadAsync({
// This is the font that we are using for our tab bar
...Icon.Ionicons.font,
...Icon.EvilIcons.font,
// We include SpaceMono because we use it in HomeScreen.js. Feel free
// to remove this if you are not using it in your app
"space-mono": require("./assets/fonts/SpaceMono-Regular.ttf"),
questrial: require("./assets/fonts/Questrial-Regular.ttf"),
Roboto_medium: require("native-base/Fonts/Roboto_medium.ttf"),
PatuaOne: require("./assets/fonts/PatuaOne-Regular.ttf")
})
]);
};
_handleLoadingError = error => {
// In this case, you might want to report the error to your error
// reporting service, for example Sentry
console.warn(error);
};
_handleFinishLoading = () => {
this.setState({ isLoadingComplete: true });
};
}
const styles = StyleSheet.create({
container: {
flex: 1,
backgroundColor: "#fff"
}
});
You can't do this in render() method:
// As soon as app finishs loading and splash screen hides
// Check if user loggedIn
// Firebase.auth().onAuthStateChanged(user => {
// if (user) {
// this.setState({ isUserLogged: true });
// console.log(user.providerData[0].phoneNumber);
// } else {
// console.log("No user logged in yet!");
// }
// });
You add that in componentWillMount usually. As the error indicates, you are calling setState inside render which causes infinite loop.
EDIT:
Also you should unsubscribe from firebase on unmounting. That means you should do something like this this.firebaseUnsubscriber = Firebase.auth().onAuthStateChanged(user => {...}). In componentWillUnmount add if(this.firebaseUnsubscriber) this.firebaseUnsubscriber()
Any ideas why I am getting the following this "dispatch is not a function" error in my listEventsActionCreator function when it calls "dispatch(listEventsRequestedAction())" ???
If I comment out the lines in this method after the dispatch it actually then works which is strange.
Using react-create-app, with redux, typescript, thunk.
ERROR:
TypeError: dispatch(...) is not a function
CODE:
export function listEventsRequestedAction() {
return {
type: PlannerEventTypes.LIST_EVENTS_REQUESTED
}
}
export const listEventsReceivedAction = (events:PlannerEvent[]) => {
return {
type: PlannerEventTypes.LIST_EVENTS_RECEIVED,
events
}
}
export const listEventsErrorAction = (err:any) => {
return {
type: PlannerEventTypes.LIST_EVENTS_ERROR,
error: err
}
}
export const listEventsActionCreator = () => {
return (dispatch: any) => {
dispatch(listEventsRequestedAction()) // <== ERROR: TypeError: dispatch(...) is not a function
(API.graphql(graphqlOperation(listEvents)) as Promise<any>).then((results:any) => {
const events = results.data.listEvents.items
dispatch(listEventsReceivedAction(events))
}).catch((err:any) => {
// console.log("ERROR")
dispatch(listEventsErrorAction(err))
})
}
}
package.json
{
"name": "planner",
"version": "0.1.0",
"private": true,
"dependencies": {
"#types/graphql": "^14.0.7",
"#types/react-redux": "^6.0.10",
"aws-amplify": "^1.1.19",
"aws-amplify-react": "^2.3.0",
"date-fns": "^1.30.1",
"eslint": "^5.9.0",
"konva": "^2.5.1",
"moment": "^2.22.2",
"moment-timezone": "^0.5.23",
"react": "^16.6.3",
"react-dom": "^16.6.3",
"react-draggable": "^3.0.5",
"react-konva": "^16.6.31",
"react-moment": "^0.8.4",
"react-redux": "^5.1.1",
"react-scripts-ts": "3.1.0",
"redux": "^4.0.1",
"redux-logger": "^3.0.6",
"redux-thunk": "^2.3.0"
},
"scripts": {
"start": "react-scripts-ts start",
"build": "react-scripts-ts build",
"test": "react-scripts-ts test --env=jsdom",
"eject": "react-scripts-ts eject"
},
"devDependencies": {
"#types/jest": "^23.3.10",
"#types/node": "^10.12.10",
"#types/react": "^16.7.10",
"#types/react-dom": "^16.0.11",
"#types/redux-logger": "^3.0.7",
"typescript": "^3.2.1"
}
}
index.tsx
import * as React from 'react'
import { render } from 'react-dom'
import { Provider } from 'react-redux'
import { applyMiddleware, createStore } from 'redux'
import App from './App'
import './index.css'
import rootReducer from './reducers/index'
import registerServiceWorker from './registerServiceWorker'
import { createLogger } from 'redux-logger'
import thunkMiddleware from 'redux-thunk'
const loggerMiddleware = createLogger()
const store = createStore (
rootReducer,
applyMiddleware(
thunkMiddleware, // lets us dispatch() functions
loggerMiddleware // neat middleware that logs actions
)
)
render(
<Provider store={store}>
<App testStr='test' />
</Provider>
,document.getElementById('root') as HTMLElement
);
registerServiceWorker();
The problem is because of the syntax that you followed. You don't have a semicolon after dispatch(listEventsRequestedAction()) and since you follow it up with (API.graphql(graphqlOperation(listEvents) as Promise<any>) while compiling it is evaluted as dispatch(listEventsRequestedAction())(API.graphql(graphqlOperation(listEvents) as Promise<any>) and hence it gives you the error.
Adding a semicolon after dispatch(listEventsRequestedAction()) would work
export const listEventsActionCreator = () => {
return (dispatch: any) => {
dispatch(listEventsRequestedAction());
(API.graphql(graphqlOperation(listEvents)) as Promise<any>).then((results:any) => {
const events = results.data.listEvents.items
dispatch(listEventsReceivedAction(events))
}).catch((err:any) => {
// console.log("ERROR")
dispatch(listEventsErrorAction(err))
})
}
}
P.S. The semicolon is not required in Javascript and would not cause a
js error on its own. It could however cause an error if concatenating
with other scripts.