redux-next-wrapper with supabase v2 ssr - reactjs

Before supabase V2 I got my data and stored in with redux like this:
supabase V2 broke unfortunately some functionality with redux-next-wrapper
export const getServerSideProps = wrapper.getServerSideProps(
(store) => async ({ req }) => {
const { user } = await supabase.auth.api.getUserByCookie(req);
if (user === null) {
return {
redirect: {
permanent: false,
destination: "/auth",
},
props: {},
};
}
if (user) {
async function getData() {
let { data, error, status } = await supabase
.from("table")
.select(`id`)
.eq("id", user.id);
store.dispatch(writeUserData(data));
return data;
}
return {
props: {
data: await getData(),
},
};
}
}
);
Any ideas how I can achieve the same functionality with withPageAuth()?
export const getServerSideProps = withPageAuth({
redirectTo: '/foo',
async getServerSideProps (ctx, supabase) {
// Access the user object
const {
data: { user }
} = await supabase.auth.getUser()
return { props: { id: user?.id } }
}
})

This would be similar to what you already have except that the redirect is handled by the withPageAuth already.
export const getServerSideProps = withPageAuth({
redirectTo: '/auth',
async getServerSideProps (ctx, supabase) {
// Access the user object
const {
data: { user }
} = await supabase.auth.getUser()
let { data, error, status } = await supabase
.from("table")
.select(`id`)
.eq("id", user.id);
store.dispatch(writeUserData(data));
return { props: { data } }
}
})

Related

firebase react cloud messaging push notification [duplicate]

I was working on a project using Firebase cloud messaging react. I was sending this to my server, but it doesn't work. Surely I have tried, but I don't know what's wrong again.
Below is the code.
Here it sends a POST request to Firebase, and it should send a notification to the user.
async function sendNotification(id, userMessage) {
const headers = {
'Authorization': `key=${code}`,
'Content-Type': 'application/json'
}
const message = {
'to': `${id}`,
'content_available': true,
'apns_priority': 5,
'notification': {
body: `${userMessage}`
},
const url = 'https://fcm.googleapis.com/fcm/send'
//console.log(code)
await axios.post(url, message, {
headers: headers
})
}
const sendMessageToServer = async (e) => {
//e.preventDefault();
toggle()
const docRe = doc(database, "help", mailer);
const data = {
email: user.email,
user: newMessage,
}
//console.log(data, 'not clear')
setNewMessage('')
//console.log(data, newMessage, 'cleared')
setShow(false)
if(newMessage === '') {
}
else {
const docRef = doc(database, "users", mailer);
await updateDoc(docRe, {
msg: arrayUnion(data)
})
.then(() => {
async function p() {
const id = await getDoc(docRef)
//console.log(id.data())
sendNotification(id.data().notice, `Admin : ${data.user}`)
}
p()
})
}
Sometimes it sends to my localhost because I tested there, but it doesn't work on my Netlify app. Secondly, I noticed that it keeps generating the same token for each user, but that's not the issue, but if you can help in both I would be grateful.
export default function Dashboard() {
async function callToken() {
await getToken(messaging, {vapidKey: process.env.NOTIFICATION})
.then((code) => {
//console.log(code)
async function docRef() {
const dc = doc(database, "users", auth.currentUser.email);
await updateDoc(dc, {
notice: code
});
}
docRef()
})
}
async function requestPermission() {
await Notification.requestPermission()
.then((permission) => {
if (permission === 'granted') {
console.log('Notification permission granted.')
callToken()
}
})
}
const goTo = useNavigate();
useEffect(() => {
onAuthStateChanged(auth, (data) => {
if(!data) {
goTo('/login')
}
else {
currentBalance();
requestPermission()
}
})
})
}
Please know I imported all required modules.

react-query custom hook how to use useMutation and useQuery conditionaly

i create custom hook for use useQuery() :
export const useRequest = (
{
path = "",
params = {},
body = {},
key = "",
options= {},
method = "get"
}
) => {
// async function for get API:
const callApi = async () => {
const { data: { response } } = await axios[method](baseUrl._serviceUrl + path,
{
params,
...body
});
return response;
}
const query = useQuery(key, callApi, {
refetchOnWindowFocus: false,
...options
});
return { ...query, isLoading: query.isLoading && query.fetchStatus !== "idle" }
}
To use the useMutation hook without using the separate function, I changed my useRequest() as follows:
export const useRequest = (
{
path = "",
params = {},
body = {},
key = "",
options= {},
method = "get",
mutation = false
}
) => {
// async function for get API:
const callApi = async () => {
const { data: { response } } = await axios[method](baseUrl._serviceUrl + path,
{
params,
...body
});
return response;
}
if (mutation) {
const callMutationApi = async (data) => {
const {params, body} = data;
const { data: { response } } = await axios.post(baseUrl._serviceUrl + path,
{
params,
...body
});
return response;
}
return useMutation(callMutationApi, options);
}
const query = useQuery(key, callApi, {
refetchOnWindowFocus: false,
...options
});
return { ...query, isLoading: query.isLoading && query.fetchStatus !== "idle" }
}
But I get the following error:
React Hook "useMutation" is called conditionally. React Hooks must be called in the exact same order in every component render. Did you accidentally call a React Hook after an early return?
What changes should I make in the useRequest() function? Thank you for your guidance.
///// UPDATE /////
According to the answer of dear #kapobajza...
I changed the code as follows and it worked:
export const useRequest = (
{
path = "",
params = {},
body = {},
key = "",
options= {},
method = "get",
mutation = false
}
) => {
// async function for get API:
const callApi = async () => {
const { data: { response } } = await axios[method](baseUrl._serviceUrl + path,
{
params,
...body
});
return response;
}
const callMutationApi = async (data) => {
const {params, body} = data;
const { data: { response } } = await axios.post(baseUrl._serviceUrl + path,
{
params,
...body
});
return response;
}
// Instead of returning here, just save the result in a variable
const useMutationResult = useMutation(callMutationApi, options);
const query = useQuery(key, callApi, {
refetchOnWindowFocus: false,
enabled: (!mutation && options?.enabled),
...options
});
// If mutation is defined, return that result
if (mutation) {
return useMutationResult;
}
return { ...query, isLoading: query.isLoading && query.fetchStatus !== "idle" }
}
I added the option part of the following code to useQuery().. This will prevent useQuery() from running:
{
refetchOnWindowFocus: false,
enabled: (!mutation && options?.enabled),
...options
}
Please tell me if this solution is correct?
Unfortunately you cannot call React hooks conditionally.
One thing you'll find out early adopting react is that you cannot have conditional hooks. This is because every hook is initially added into a list that is reviewed on every render cycle, so if the hooks don't add up, there is something amiss and any linter set up correctly will warn you.
Taken from this article
But the thing you could do is to return the result of the useMutation hook if mutation is defined:
export const useRequest = (
{
path = "",
params = {},
body = {},
key = "",
options= {},
method = "get",
mutation = false
}
) => {
// async function for get API:
const callApi = async () => {
const { data: { response } } = await axios[method](baseUrl._serviceUrl + path,
{
params,
...body
});
return response;
}
const callMutationApi = async (data) => {
const {params, body} = data;
const { data: { response } } = await axios.post(baseUrl._serviceUrl + path,
{
params,
...body
});
return response;
}
// Instead of returning here, just save the result in a variable
const useMutationResult = useMutation(callMutationApi, options);
const query = useQuery(key, callApi, {
refetchOnWindowFocus: false,
...options
});
// If mutation is defined, return that result
if (mutation) {
return useMutationResult;
}
return { ...query, isLoading: query.isLoading && query.fetchStatus !== "idle" }
}

how to pass token in headers in below reactjs codesandbox link

https://codesandbox.io/s/login-authentication-usecontext-66t9t?file=/src/index.js
Here how we can pass token in headers for any other pages in codesandbox link. In my code i have action file like this. im getting my response in localstorage.how can i pass my accesstoken here as headers in this page.
import axios from 'axios';
export const upiAction = {
upi,
};
function upi(user) {
return (dispatch) => {
var data = {
upiId: user.upiId,
accountNumber: user.accountNumber,
};
axios
.post('http://localhost:9091/upiidcreation', data
)
.then((res) => {
console.log("res", (res));
const { data } = res;
alert(JSON.stringify(data.responseDesc));
// window.location.pathname = "./homes";
if (data.responseCode === "00") {
window.location.pathname = "./home"
}
})
.catch(err => {
dispatch(setUserUpiError(err, true));
alert("Please Check With details");
});
};
}
export function setUserUpi(showError) {
return {
type: 'SET_UPI_SUCCESS',
showError: showError,
};
}
export function setUserUpiError(error, showError) {
return {
type: 'SET_UPI_ERROR',
error: error,
showError: showError,
};
}

react toolkit centralize error handling for numerous createAsyncThunks

user-slice.ts
export const login = createAsyncThunk(
'user/auth-login',
async(loginData: UserLogin, { rejectWithValue }) => {
try {
const res: any = await axios.post(POST_LOGIN, {
email: loginData.email, password: loginData.password });
return res.data;
}
catch(err: any) {
popup(err.response.data['err'], 'err');
}
}
)
export const save = createAsyncThunk(
'users/save-changes',
async(updatedUser: FormData, { rejectWithValue }) => {
try {
const res: any = await axios.post(POST_SAVE, updatedUser, {
headers: { ...constructHeaders(true, true) }
})
}
catch(err: any) {
popup(err.response.data['err'], 'err');
}
}
)
export const signUp = createAsyncThunk(
'user/auth-signup',
async(newUserData: FormData, { rejectWithValue }) => {
try {
const res: any = await axios.post(POST_SIGNUP, newUserData, {
headers: { ...HEADERS_FILE }
})
return res.data;
}
catch(err: any) {
popup(err.response.data['err'], 'err');
return rejectWithValue(err.response.data['err']);
}
}
)
Let's say I have these, instead of putting try/catch blocks for every single one of them, I want to centralize it to reduce code and just display a popup for the user, is it possible with just a class or does rtk have something specifically for this?

dispatch thunk return to component

I'm trying to pass the response of a dispatched function back to my component code. I get an signed request from my backend then upload the file from my component.
my component code here get's an S3 signature from my backend to upload a file
handleSubmitClick = async () => {
if (this.state.name){
let newFile = {
filename: this.state.name,
filetype: this.state.media.type,
}
this.props.signS3(newFile.filename, newFile.filetype)
.then( res => console.log('NO RESPONSE', res))
this.handleCloseClick();
} else {
this.setState({ inputError: true });
}
}
i get signS3 from mapdispatchtoprops
const mapDispatchToProps = dispatch => {
return {
handleCancelClick() {
dispatch(openAttachAssetModal(false));
},
signS3(filename, filetype) {
dispatch(signS3(filename, filetype));
}
}
}
It runs my mutation
export function signS3(filename, filetype) {
return function thunk(dispatch) {
const client = ApolloClient();
return client.mutate({
variables: { filename, filetype },
mutation: gql`
mutation signS3($filename: String!, $filetype: String!){
signS3(input: {
filename: $filename
filetype: $filetype
}) {
signedRequest
url
}
}
`
})
.then(response => {
return response
})
}
}
except I don't get a response returned...
In mapDispatchToProps you have to return what you're dispatching (in this case a promise) in signS3 otherwise the value will be undefined.
// ...
signS3(filename, filetype) {
return dispatch(signS3(filename, filetype));
}

Resources