How to Fix "Cannot read property 'then' of undefined" in JS
The "Uncaught TypeError: Cannot read properties of undefined (reading 'then')" error occurs in JavaScript whenever you try to chain a then
callback from a function that doesn't return anything:
const getPosts = () => {
fetch('https://jsonplaceholder.typicode.com/posts')
.then(data => data.json())
}
// β This will throw: Uncaught TypeError: Cannot read properties of undefined (reading 'then')
getPosts().then(data => console.log(data))
In the above example, we use the Fetch API to retrieve some posts from a remote REST API, and we want to consume the data inside a then
callback. However, the above example will throw an error because the function doesn't return anything.
How to Fix the Error
In order to fix the error, you need to ensure that a promise is returned from the function. Put a return
keyword in front of the fetch
function to fix the error:
const getPosts = () => {
return fetch('https://jsonplaceholder.typicode.com/posts')
.then(data => data.json())
}
// βοΈ This will work as the function returns a promise
getPosts().then(data => console.log(data))
In case no other logic is needed inside the function, we can omit the return
keyword inside arrow functions by also removing the curly braces. The following code achieves the same result as the one above:
const getPosts = () => fetch('https://jsonplaceholder.typicode.com/posts')
.then(data => data.json())
Returning Promises Without Fetch
In some cases, you may need to construct a promise yourself without using the Fetch API. Let's take the following example where we return static data from a function, and we want to use a then
callback:
const post = {
id: 1,
title: '...',
body: '...'
}
// β This will throw the above error
const getPost = () => post
// Or using explicit return
const getPost = () => {
return post
}
// βοΈ This will ensure the value is returned as a promise
const getPost = () => Promise.resolve(post)
In the first example, the function returns the object as-is, hence we get the same error because the return value is not a promise. To turn it into a promise without using the Fetch API, we need to call Promise.resolve
, with the value that we want to resolve.
For this simple example, you don't need to use a promise. Only use this approach when you don't know the value of post
upfront, and it can be either a promise or not. In such cases, Promise.resolve
helps you ensure that a promise is always returned.
Conclusion
When nothing is returned from a function, it will implicitly return undefined
. We can also verify this by using the typeof
operator on the invoked function:
const getPosts = () => {}
// This will return 'undefined'
typeof getPosts()
Note that when encountering the above error, you always need to return a promise, as all promises are so-called thenables (but not all thenables are promises). A thenable is an object that implements a then
method that can be chained from the object, usually a promise.
If you would like to learn more about how the Fetch API and promises work in JavaScript, make sure you check out the following lesson where we dive deeper into the API, as well as how to handle responses and errors.
Rocket Launch Your Career
Speed up your learning progress with our mentorship program. Join as a mentee to unlock the full potential of Webtips and get a personalized learning experience by experts to master the following frontend technologies: