Blog I followed : https://medium.com/#sarafathulla/how-to-add-firebase-push-notifications-in-next-js-react-8eecc56b5cab
I did the exact same process, but I cant see notifications in my console or anywhere.
It was not mentioned in which file we have to do this part so I did in my _app.js in pages folder:
import "../styles/globals.css";
import { firebaseCloudMessaging } from "../webPush";
import "firebase/messaging";
import firebase from "firebase/app";
import "react-quill/dist/quill.snow.css";
function MyApp({ Component, pageProps }) {
React.useEffect(() => {
setToken();
async function setToken() {
try {
const token = await firebaseCloudMessaging.init();
if (token) {
console.log("checking token");
getMessage();
}
} catch (error) {
console.log(error);
}
}
function getMessage() {
const messaging = firebase.messaging();
messaging.onMessage((message) => console.log("foreground ", message));
}
},[]);
React.useEffect(() => {
// Remove the server-side injected CSS.
const jssStyles = document.querySelector("#jss-server-side");
if (jssStyles) {
jssStyles.parentElement.removeChild(jssStyles);
}
}, []);
return <Component {...pageProps} />;
}
export default MyApp;
Rest of the files are exactly the same as mentioned in the blog. There are no errors in console. When I try to send POST from postman I receive the following:
{
"multicast_id": 5967494073963735539,
"success": 1,
"failure": 0,
"canonical_ids": 0,
"results": [
{
"message_id": "0:1601972416385592%e609af1cf9fd7ecd"
}
]
}
Can someone help me out here? I can't figure out what I'm doing wrong.
Related
Expected type 'pa', but it was: a custom Promise object
Hello everyone, I am new on asking questions on Stack overflow so,
i need a guide to solve this issue here. Here in this code, I am trying to implement the Stripe checkout functionality to redirect the user to the stripe checkout page. But, when i click on the loadCheckout() button this error keeps coming. Can anybody help me fix this error ?
import { collection, getDocs, where, query, addDoc } from 'firebase/firestore/lite';
import { onSnapshot } from 'firebase/firestore';
import React, { useEffect, useState } from 'react';
import { useSelector } from 'react-redux';
import { selectUser } from '../features/userSlice';
import db from '../firebase';
import './Plans.css';
import { loadStripe } from '#stripe/stripe-js';
const Plans = () => {
const [products, setProducts] = useState([]);
const user = useSelector(selectUser);
useEffect(() => {
if(collection) {
getDocs(query(collection(db, 'products'), where('active', "==", true)))
.then((querySnapshot) => {
const products = {}
querySnapshot.forEach(async (productDoc) => {
products[productDoc.id] = productDoc.data();
const priceSnap = await getDocs(query(collection(db, `products/${productDoc.id}/prices`)));
priceSnap.docs.forEach((price) => {
products[productDoc.id].prices = {
priceId: price.id,
...price.data(),
};
});
setProducts(products);
});
return querySnapshot;
});
}
}, []);
const loadCheckout = async (priceId) => {
const firstQ = collection(db, `customers/${user.uid}/checkout_sessions`);
const secondQ = query(
addDoc(firstQ, {
price: priceId,
success_url: window.location.origin,
cancel_url: window.location.origin,
})
);
onSnapshot(secondQ, async (snap) => {
const { error, sessionId } = snap.data();
if(error) {
// show error to the customer
// inspect the cloud function logs in the firebase console.
alert(`An error occurred: ${error.message}`);
}
if (sessionId) {
// we have a stripe checkout url, let's redirect
const stripe = await loadStripe(
'pk_test_51LnQj5K41BCUjAV1QSW7AAeX3XMzWJZLUNPNPKPKtHojs4wj9ECSky68tcluQQkCGMsgrA6wMQ58C0uYEWdUALja00CNIYgnnb');
stripe.redirectToCheckout({ sessionId });
}
});
}
return (
<div className='plans'>
{Object.entries(products).map(([productId, productData], index) => {
// add some logic to check if the user's subscription is active...
return (
<div key={index} className='plans__plan'>
<div className='plans__info'>
<h5>{productData.name}</h5>
<h6>{productData.description}</h6>
</div>
<button onClick={() => loadCheckout(productData.prices.priceId)}>
Subscribe
</button>
</div>
);
})}
</div>
)
}
export default Plans;
Error shown image
here's the jist of where I'm stuck (or just read the title for my question).
I have a firebase.js file where I have functions to authenticate. signinGithub, signinGoogle, signinEmail and so forth. The Firebase Auth business logic is in these functions.
I am showing errors with console.log or alert from these functions. The functions are imported into a Component and I don't know how to capture the functions result into the component by somehow setting state from this out-of-component function file.
Here's a basic example:
firebase.js
...
const signInWithGitHub = async () => {
try {
const res = await signInWithPopup(auth, githubProvider)
const user = res.user
} catch (err) {
alert(err) // ** I want to pass "err" from here to Login
// ** component by updating Logins state for a message
}
}
export {signinWithGitHub}
...
Login.jsx
import React, { useEffect, useState } from "react"
import { useAuthState } from "react-firebase-hooks/auth"
import {
auth,
signInWithGitHub
} from "../lib/firebase"
function Login() {
const [user, loading, error] = useAuthState(auth)
render(
{* Below is the method call from the imported custom firebase function *}
<button onClick={signInWithGitHub}>
Login with GitHub
</button>
)
}
...
I was thinking something like this but I can't fully resolve it in my mind:
Set state in Login.js const [message, setMessage] = useState('')
When the imported signinWithGitHub has an error message --
I'm stuck figuring out how to apply to function message to the state, any ideas?
You can create a custom function inside your Login. jsx file to call the original signInWithGitHub method with a try catch block. And more importantly, you should not use render inside a functional component. Use return to render the JSX in DOM.
firebase.js
export const signInWithGitHub = async () => {
try {
const res = await signInWithPopup(auth, githubProvider);
const user = res.user;
} catch (err) {
throw new Error(err?.message || "Unable to sign in with GitHub");
}
};
Login.jsx
import React, { useEffect, useState } from "react";
import { useAuthState } from "react-firebase-hooks/auth";
import { auth, signInWithGitHub } from "../lib/firebase";
function Login() {
const [user, loading, error] = useAuthState(auth);
const [errorMessage, setErrorMessage] = useState("");
const onLogin = async () => {
try {
await signInWithGitHub();
} catch (err) {
setErrorMessage(err);
}
};
return (
<>
<button onClick={onLogin}>Login with GitHub</button>
{!!errorMessage && <h5>{errorMessage}</h5>}
</>
);
}
I tried to implement a SSG application in Amplify with Next.js following this tutorial
pages/index.tsx worked well. But pages/posts/[id].tsx doesn't work and showed the following error.
Server Error
Error: No current user
This error happened while generating the page. Any console logs will be displayed in the terminal window.
And also the console showed this error.
GET http://localhost:3000/posts/da53d1f3-775f-49c4-a311-d311f2e5623f 500 (Internal Server Error)
My code in pages/posts/[id].tsx is following.
May I have your idea how to resolve this error?
import { Amplify, API, withSSRContext } from "aws-amplify";
import Head from "next/head";
import { useRouter } from "next/router";
import awsExports from "../../aws-exports";
import { getPost, listPosts } from "../../graphql/queries";
Amplify.configure({ ...awsExports, ssr: true });
export async function getStaticPaths() {
const SSR = withSSRContext();
const { data } = await SSR.API.graphql({ query: listPosts });
const paths = data.listPosts.items.map((post: any) => ({
params: { id: post.id },
}));
return {
fallback: true,
paths,
};
}
export async function getStaticProps({ params }: { params: any }) {
const SSR = withSSRContext();
const { data } = await SSR.API.graphql({
query: getPost,
variables: {
id: params.id,
},
});
return {
props: {
post: data.getPost,
},
};
}
export default function Post({ post }: { post: any }) {
const router = useRouter();
if (router.isFallback) {
return (
<div>
<h1>Loading…</h1>
</div>
);
}
return (
<div>
<h1>{post.title}</h1>
<p>{post.content}</p>
</div>
);
}
I am trying to write a function that will handle getting data to and from a server. This function takes the url to contact and uses the token to authorize itself against the server. This function is quite long. I would therefore want every other page in my react app to call this function with the needed url and then let this function handle everything else. I therefore need each page to await this function but I get "Error: Invalid hook call" no matter what I try.
This is the function that handles post requests to the server:
import React, { useEffect, useState, createRef, lazy, useContext } from "react";
import { UserContext } from "./UserContext";
import jwt_decode from "jwt-decode";
import axios from "axios";
export async function getProtectedAsset(url) {
const { user, setUser } = useContext(UserContext);
//If we do not have a token
if (user["userID"] == -1) {
return "Error: No token";
} else {
try {
//Get user data
const token = {
accessToken: user["accessToken"],
email: user["email"],
userID: user["userID"],
};
//Check if accessToken is about to expire (60s mairgain)
if (
Date.now() >=
jwt_decode(token["accessToken"])["exp"] * 1000 - 60000
) {
//Get new token
const res = await axios
.post("http://127.0.0.1:5002/refreshtoken", {
token: user["refreshToken"],
})
.then((res) => {
setUser({
userID: user["userID"],
email: user["email"],
accessToken: res.data["accessToken"],
refreshToken: user["refreshToken"],
accountType: user["accountType"],
});
})
.catch((err) => {
console.error(err);
});
}
//Our token is fresh
else {
const res = await axios
.post(url, token)
.then((promise) => {
return promise.data;
})
.catch((err) => {
console.error(err);
});
}
} catch (error) {
console.log(error);
throw err;
}
}
}
This is the page/component that I try to call this function from:
import React, { useState, useContext, useEffect, useCallback } from "react";
import { UserContext } from "../../UserContext";
import { getProtectedAsset } from "../../getProtectedAsset";
const Settings = () => {
const { user, setUser } = useContext(UserContext);
useEffect(async () => {
try {
let data = await getProtectedAsset("http://127.0.0.1:5002/mypage");
console.log(data);
} catch (error) {
console.error(error.message);
}
}, []);
return <></>;
};
export default Settings;
This gives me the error:
Invalid hook call. Hooks can only be called inside of the body of a
function component. This could happen for one of the following
reasons:
You might have mismatching versions of React and the renderer (such as React DOM)
You might be breaking the Rules of Hooks
You might have more than one copy of React in the same app See https://reactjs.org/link/invalid-hook-call for tips about how to debug
and fix this problem.
I have tried everything I can imagine and read different tutorials/guides/docs but still cannot figure out the problem. Usually it is the lack of knowledge, or some thinking mistakes, but I really need help with this one!
Thank you for your help
Its because you are using useContext() hook inside getProtectedAsset() function.
Instead of using useContext inside getProtectedAsset try to pass user as parameter like url to the function.
let data = await getProtectedAsset(url, user);
// Want to show spinner while posting and then success/error message using react-toastify
Is it possible?
axios.post("/orders.json", order)
.then((response) => {
console.log(response.status);
})
.catch((error) => {
console.log(error);
});
import { toast } from "react-toastify";
const promise=axios.post("/orders.json", order)
const res = await toast.promise(promise, {
pending: "Posting",
success: "Posted",
error: "error message",
});
Yes it is possible. You can have a state called isLoading and you can set it to true when you submit a post request and you can check for isLoading before rendering your component like below.
if(isLoading) {
return (<Spinner />)
}
And you can use toast to show success/error message after post method is executed.
Like below
toast.error('Sorry request failed')
or
toast.success('Request successfull')
But before use toast you have wrap your App component in toast container like below.
import React from 'react';
import { ToastContainer, toast } from 'react-toastify';
import 'react-toastify/dist/ReactToastify.css';
function App(){
const notify = () => toast("Wow so easy!");
return (
<div>
<button onClick={notify}>Notify!</button>
<ToastContainer />
</div>
);
}
This will solve your question.
import React, { useEffect, useState } from "react";
import axios from "axios";
import { toast } from "react-toastify";
import 'react-toastify/dist/ReactToastify.css';
toast.configure({
position: toast.POSITION.BOTTOM_RIGHT
});
export default function App() {
const [state, setState] = useState({
loading: true,
dataArray: []
});
const myRequest = async () => {
try {
const request = await axios.get(`/generic_data/search_skills`);
const { error, msg, data } = request.data;
if (error) throw new Error(msg);
setState({ ...state, loading: false, dataArray: data });
toast.success("All good, we have the data");
} catch (e) {
toast.error("Upps, someting went wrong");
}
};
useEffect(()=>{
myRequest()
},[])
if (state.loading) {
return "Loading data from server.. this will take long time...";
}
return <div>The request has ended. We have the data</div>;
}