I am trying to use getInitialProps to get items from a firebase database, but to do so, I need the current user Id. However when i pass the user id object as a context to getInitialProps, it is null. Please help.
inside the main dashboard method, I have access to auth.currentUser.uid, but it appears null when I try to use it in get initial props
Dashboard.getInitialProps = async (context) => {
console.log(auth?.currentUser?.uid);
console.log("is this working");
const userRef = ref(database, "users/" + auth?.currentUser?.uid);
const getUser = async () => (await get(userRef)).val();
const data = await getUser();
const userInfo = await data;
console.log(userInfo);
if (!userInfo) return { notFound: true };
return {
props: userInfo,
};
};
Related
I'm trying to get the current temperature from openweathermaps using axios.
I can put my url into the browser and it works fine. But when I try do an axios call with the correct url it doesnt event call.
Here is the relevant code section:
function Overview() {
const [temperature, setTemperature] = useState('')
const API_KEY = '{apikey}'
const getTemperature = useCallback(async () => {
const url = `https://api.openweathermap.org/data/2.5/weather?lat=${latitude.toFixed(2)}&lon=${longitude.toFixed(
2,
)}&appid=${API_KEY}`
console.log('my provided url is set to:', url)
const response = await axios.get(url)
if (response.data) {
setTemperature(response.data.main.temp)
}
}, [latitude, longitude])
useEffect(() => {
getTemperature().catch(console.error)
}, [getTemperature])
return <>{temperature ? temperature : 'no data'}</>
}
Any help as to where I'm going wrong would be great as I just cant see my error!
Your URL working on the browser showcases that your API key is correct. Now, make sure the variables in your URL are properly set from the code, particularly the API key. you can console.log them to be sure. Passed that, the minimal code below would do.
import {useCallback, useEffect} from 'react';
import axios from 'axios';
function Overview() {
// YOUR_INITIAL_STATE rather be undefined
const [temperature, setTemperature] = useState(YOUR_INITIAL_STATE);
const API_KEY = 'YOUR_API_KEY';
const getTemperature = useCallback(async () => {
const url = `https://api.openweathermap.org/data/2.5/weather?lat=${latitude}&lon=${longitude}&appid=${API_KEY}`;
console.log("my provided url is set to:", url);
const response = await axios.get(url);
if(response.data){
setTemperature(response.data.main.temp);
}
// only call the functtion when these deps change
}, [latitude, longitude])
useEffect(() => {
// Check the error for further debbugging
getTemperature()
.catch(console.error);
}, [getTemperature])
return (
<>
{temperature ? temperature : "no data"}
</>
);
}
It looks like your arrow function is calling itself recursively:
const setTemperature = async () => {
const response = await axios.get(`https://api.openweathermap.org/data/2.5/weather?lat=${latitude}&lon=${longitude}&appid=${API_KEY}`);
setTemperature(response.data.main.temp);
};
Your code doesn't show where this is being called. Probably it needs to be something like:
const setTemperature = async () => {
const response = await axios.get(`https://api.openweathermap.org/data/2.5/weather?lat=${latitude}&lon=${longitude}&appid=${API_KEY}`);
return response.data.main.temp;
};
Perhaps it just needs to be a one letter change:
const getTemperature = async () => {
const response = await axios.get(`https://api.openweathermap.org/data/2.5/weather?lat=${latitude}&lon=${longitude}&appid=${API_KEY}`);
setTemperature(response.data.main.temp);
};
Credit to #devklick
I'm trying to make a migratiion of users model from adonis to postgres but I keep getting this error Primary key value is missing for user
My model look like this:
class User extends Model {
static boot () {
super.boot()
this.addHook('beforeSave', async (userInstance) => {
if (userInstance.dirty.password) {
userInstance.password = await Hash.make(userInstance.password)
}
})
}
tokens () {
return this.hasMany('App/Models/Token')
}
}
module.exports = User
And the migration I'm trying to run is:
/** #type {import('#adonisjs/lucid/src/Schema')} */
const Schema = use('Schema')
class UserSchema extends Schema {
up () {
this.create('users', (table) => {
table.increments()
table.string('username', 80).notNullable().unique()
table.string('email', 254).notNullable().unique()
table.string('password', 60).notNullable()
table.timestamps()
})
}
down () {
this.drop('users')
}
}
module.exports = UserSchema
I tried adding primary() to table.increments() asuming it is generating the auto increments id in postgre database. When I check the database the user is sometimes added, but with id's that goes from 2 to 4 and so on
The controller looks like this
const User = use('App/Models/User')
class UserController {
async register({request, auth, response}) {
const username = request.input("username")
const email = request.input("email")
const password = request.input("password")
let user = new User()
user.username = username
user.email = email
user.password = password
user = await user.save()
let accessToken = await auth.generate(user)
return response.json({"user": user, "access_token": accessToken})
}
async login({request, auth, response}) {
const email = request.input("email")
const password = request.input("password");
try {
if (await auth.attempt(email, password)) {
let user = await User.findBy('email', email)
let accessToken = await auth.generate(user)
return response.json({"user":user, "access_token": accessToken})
}
}
catch (e) {
return response.json({message: 'You first need to register!'})
}
}
show ({ auth, params }) {
if (auth.user.id !== Number(params.id)) {
return "You cannot see someone else's profile"
}
return auth.user
}
}
module.exports = UserController
The problem is that you overwrite user model instance in user = await user.save().
as #Costin say's simply storing result of await user.save() in new variable will solve the issue.
for example:
...
let saved = await user.save()
let accessToken = await auth.generate(user)
...
table.increments() need column name as parameter -> table.increments(name)
Please read official knex documentation : https://knexjs.org/#Schema-increments
Example :
table.increments('id').primary()
The issue is with
user = await user.save()
that will return true when user is saved to db, passing that to auth.generate is what cause that error.
Just use something like
let success = await user.save()
and check success value after. Might want to return the token and 200 status only if user is saved (success is true).
I am writing a test which tests a firebase trigger. The problem, however, is that I cannot make it work.
I want to use the local firestore emulator and Jest in order to simulate a change in the firestore and see if the trigger does what it needs to do.
I require the cloud function in my test and I initialize my app
Setup.js:
const firebase = require('#firebase/testing');
const PROJECT_ID = 'project';
let admin;
let db;
const setupAdmin = async () => {
admin = firebase.initializeAdminApp({
projectId: PROJECT_ID
});
db = admin.firestore();
};
const getAdmin = () => {
return admin;
};
const getDb = () => {
return db;
};
module.exports.setupAdmin = setupAdmin;
module.exports.getAdmin = getAdmin;
module.exports.getDb = getDb;
Test.js
describe('Billing', () => {
let dbRef;
beforeAll(async () => {
const {db, admin} = require('../../../functions/helpers/setup');
dbRef = db;
});
afterAll(async () => {
await Promise.all(firebase.apps().map(app => app.delete()));
console.log(`View rule coverage information at ${COVERAGE_URL}\n`);
});
it('test', async () => {
const mockData = {
'Users/user1': {
uid: 'user1'
},
['Users/user1/Taxes/' + new Date().getFullYear().toString()]: {
totalExpenseEuro: 0
}
};
for (const key in mockData) {
const ref = dbRef.doc(key);
await ref.set(mockData[key]);
}
// Create mockup data
await dbRef.collection('Users').doc('user1').collection('Expenses').doc('expense1').set({
amountEuroInclVAT: 100
});
// Make snapshot for state of database beforehand
const beforeSnap = test.firestore.makeDocumentSnapshot({amountEuroInclVAT: 0}, 'Users/user1/Expenses/expense1');
// Make snapshot for state of database after the change
const afterSnap = test.firestore.makeDocumentSnapshot(
{amountEuroInclVAT: 100},
'Users/user1/Expenses/expense1'
);
const change = test.makeChange(beforeSnap, afterSnap);
// Call wrapped function with the Change object
const wrapped = test.wrap(calculateTaxesOnExpenseUpdate);
wrapped(change, {
params: {
uid: 'test1'
}
});
});
});
Now the main problem comes when I try to access this db object in my trigger
const calculateTaxesOnExpenseUpdate = functions.firestore
.document('Users/{uid}/Expenses/{expenseId}')
.onWrite(async (change, context) => {
const {getDb} = require('../helpers/setup'); // This setup is the same as above
let db = getDb();
...
For some reason when I perform an action like (await db.collection('Users').get()).get('totalExpenseEuro'), Jest stops executing my code. When I set a debugger right after that line, it never gets printed. That piece of code crashes, and I have no idea why. I think the DB instance if not properly configured in my cloud trigger function.
Question: What is a good way of sharing the DB instance (admin.firestore()) between the test and the cloud trigger functions?
I'm trying to get data from firebase. I receive the data as an Object and it shows the data I want. However when I try to get a specific value from an Object property it says it's undefined. What am I doing wrong or what am I missing?
export const createChat = () => {
return async dispatch => {
dispatch({ type: CREATE_SINGLE_CHAT });
const creator = firebase.auth().currentUser.uid;
const userRef = firebase.database().ref(`/users/${creator}`);
const currUser = await userRef.once('value');
console.log(currUser);
console.log(currUser.name);
};
};
Here is the console.log:
23:30:58 // currUser
Object {
"email": "a#b.de",
"is24Hours": true,
"name": "Alex",
}
23:30:58 // currUser.name
undefined
I'm using React Native with Redux and Redux-Thunk and also the realtime-database from firebase as database.
As Max Brodin mentioned I forgot to use the val() method from firebase:
firebase.google.com/docs/database/web/read-and-write
working code:
export const createChat = () => {
return async dispatch => {
dispatch({ type: CREATE_SINGLE_CHAT });
const creator = firebase.auth().currentUser.uid;
const userRef = firebase.database().ref(`/users/${creator}`);
const currUser = await userRef.once('value');
console.log(currUser);
console.log(currUser.val().name); // here is the change
};
};
I am succesfully updating my user's profile picture on their profile and on all of their reviews posted with this function:
export const storeUserProfileImage = (url) => {
const { currentUser } = firebase.auth();
firebase.database().ref(`/users/${currentUser.uid}/profilePic`)
.update({ url });
firebase.database().ref('reviews')
.orderByChild('username')
.equalTo('User3')
.once('value', (snapshot) => {
snapshot.forEach((child) => {
child.ref.update({ profilePic: url });
});
});
};
I am aware that I should be using an atomic update to do this so the data updates at the same time (in case a user leaves the app or something else goes wrong). I am confused on how I can accomplish this when querying over child values.
Any help or guidance would be greatly appreciated!
Declare a variable to store all the updates. Add the updates as you read them on your listener's loop. When the loop is finished, run the atomic update.
export const storeUserProfileImage = (url) => {
const { currentUser } = firebase.auth();
firebase.database().ref('reviews')
.orderByChild('username')
.equalTo('User3')
.once('value', (snapshot) => {
var updates = {};
updates[`/users/${currentUser.uid}/profilePic`] = url;
snapshot.forEach((child) => {
updates[`/reviews/${child.key}/profilePic`] = url;
});
firebase.database().ref().update(updates);
});
};