TypeError cannot seem to fix or find cause.

I have a line of code that is breaking my website, I don’t see anything wrong with the code, but i keep getting a TypeError cannot read ‘firstName’ of undefined. But i am not sure how to re-write this code another way to try to get rid of the error. Can anyone help?

import wixData from ‘wix-data’;
import wixUsers from ‘wix-users’;
import wixLocation from ‘wix-location’;
import { session } from ‘wix-storage’;

let user = wixUsers.currentUser;
let userId = user.id;
let isLoggedIn = user.loggedIn; //true

$w.onReady( async function () {
let email = await wixUsers.currentUser.getEmail();
let userDetails = ( await wixData.query(“Register”).eq(“title”, email).find()).items[0];
let firstName = userDetails.firstName;
$w(‘#memberName’).text = ${firstName};

let referralCode = userId.split(“-”)[4];
$w(‘#referral’).text = referralCode; //generates referral code to update database
$w(‘#button2’).onClick(() => {
console.log(userDetails);
let toUpdate = userDetails;
toUpdate.referralCode = referralCode,
wixData.update(“Register”, toUpdate)
.then((results) => {
let item = results; //see item below
// wixLocation.to(“/home”);
wixLocation.to(“/plans-pricing”);
})
. catch ((err) => {

        console.log(err) 
    }); 
}); 

});

I am also getting a Failed to fetch error in the preview console

Basically you have a problem with your wixData query on the Register data collection.

You should try not to mix up promise and a sync patterns in the same function #1 it makes debugging hard and doesn’t help readability.

#2 You are trying to merge several commands into one line where you may have an error and you are not considering this. You should always code defensively for this reason.

I would stay away from the asynchronous await pattern until you have your Code working or at least wrap the calls in a try catch structure.

Let your query.find complete first. Test it’s return and then decide whether you can assign to userDetails or not. At the moment you are probably not getting a response to your query and userDetails is undefined which is leading to the type error. Since you don’t catch errors you wont see what is going wrong.

Thank you for your input Steve, i will try to figure out how to do the things suggested. This was done by a coder i hired to help build my site. Everything was working and then it stopped and of course now my coder is a bit MIA so i am left to figure it out.

Here is a refactoring of your code to try to give you some hints…

import wixData from 'wix-data';
import wixUsers from 'wix-users';
import wixLocation from 'wix-location';
import { session } from 'wix-storage';
let user = wixUsers.currentUser;
let userId = user.id;
let isLoggedIn = user.loggedIn; //true

$w.onReady(async function () {
    let email = await wixUsers.currentUser.getEmail();
    let userDetails = (await wixData.query("Register").eq("title", email).find()).items[0];
    
    //vvvvvvvvvvvvvv This is the line of code that is failing vvvvvvvvvvvvvvvvvv
    let firstName = userDetails.firstName; // Cannot read property firstName of undefined!!
    // The property in this call is ^^^^^ -> firstname
    // undefined in the error is the variable that firstName is a property of --> userDetails
   
    

Where did userDetails come from? Well it is the line above which reads…

let userDetails = (await wixData.query("Register").eq("title", email).find()).items[0];

So you need to catch the error and do something with it. Also you should examine the line of code and see if it is doing what you expect.

// Since you already have a then catch block in the code then we should simply retain this
// pattern for simplicity. 
// We will remove the await pattern and test the query before we try to extract information from it. 

wixData.query("Register")
.eq("title", email)
.limit(1) // Add this to force a single response
.find()
.then((queryResponse) => {
    // Did we get a result that we can use?
    if (queryResponse.length !== 0) {
        // We didn't find a match so we have an error
        throw Error(`No records for ${email}`);
    }
    // If we get here then we have something we can work with
    // We know from the previous test that the items array has one record
    let userDetails = queryResponse.items[0];
    
    // Continue our code here...
});

So if we look at a refactored version of the code you have above you get this…

import wixData from 'wix-data';
import wixUsers from 'wix-users';
import wixLocation from 'wix-location';
import { session } from 'wix-storage';
let user = wixUsers.currentUser;
let userId = user.id;
let isLoggedIn = user.loggedIn; //true
// userDetails is a global variable used in onReady AND onClick we start with a null (undefined) 
// Value so need to check it before it is used for reading incase it isn't set in onReady.
let userDetails = null; 

$w.onReady(function () {

    // Initialise user details if we have any.
    wixUsers.currentUser.getEmail()
    .then((email) => {
        if (!email) {
            throw Error("currentUser doesn't have an email address");
        }
        // We return the query because we are in a Promise chain
        return wixData.query("Register")
        .eq("title", email)
        .find();
    })
    .then((queryResponse) => {
        // Did we get a result that we can use?
        if (queryResponse.length !== 0) {
            // We didn't find a match so we have an error
            throw Error(`No records for ${email}`);
        }
        // If we get here then we have something we can work with
        // We know from the previous test that the items array has one record
        userDetails = queryResponse.items[0];     

        let firstName = userDetails.firstName;
        $w('#memberName').text = `${firstName}`;
        let referralCode = userId.split("-")[4];
        $w('#referral').text = referralCode; //generates referral code to update database     
    })
    // Handle errors in one place. The errors we throw above will come here as well as errors
    // From the other function calls
    .catch((error) => {
        console.log(error.message);
    });
    
    // Button click handler
    $w('#button2').onClick(() => {
        console.log(userDetails);
        
        // Remember from above - userDetails may be null so let's make sure we have a value
        // Before we use it.
        if (!userDetails) {
            console.log('We don't have any user details!');
        } else {
            // We have a value for the userDetails record
            // Add a referral code to it.
            userDetails.referralCode = referralCode;
            // Save it back to the data collection
            // Save performs an insert OR and update so more versatile.
            wixData.save("Register", userDetails)
            .then((results) => {
                // Not sure why this is here >>>> let item = results; //see item below
                // wixLocation.to("/home");
                wixLocation.to("/plans-pricing");
            })
            .catch((err) => {
                console.log(err.message);
            });
        }
        
    });
};

This is awesome Steve, this really explains and helps me understand. Thank you so very much for taking the time to explain not only what to do, but to understand why were doing what were doing.