_Errors_Error__WEBPACK_IMPORTED_MODULE_4__.default is not a constructor
Today was my mid-mod assessment for Mod 3 at Turing! That's a lot of Turing-specific lingo, but basically this is an ungraded assessment of everything we've learned so far at the halfway point of the 3rd quarter of this program (that's not actually less confusing, is it?). We were given a partially-completed single-page React App and several features to complete and test within a 3 hour time limit. Three of the five features were required in order to be on track at this point in the Mod, anything else was the cherry on top.
The app initially just displayed a page with a background image and a header for the "Turing Cafe Reservations"-- our job was to fetch the current reservations from an API, display them on the page, create a controlled form to add a new reservation, and write tests in Cypress to cover the entire user flow of creating a new reservation.
This is the comp that was provided, the styling was super minimal and easy to implement... Turing is, after all, not a design school:
I made it through those initial iterations with over an hour to spare so I moved on to some of the "extensions" and added POST
and DELETE
functionality. Great! With 20 minutes to go, I moved onto some error handling and conditional rendering of error messages. I was already implementing a checkForErrors
function as part of my API calls, but I realized that I had neglected to add a .catch
block and set those errors in state so I patched that up quickly.
componentDidMount() {
fetch('http://localhost:3001/api/v1/reservations')
.then(res => this.checkForErrors(res))
.then(data => this.setState({ reservations: data }))
.catch(err => this.setState({ error: err.message }));
}
checkForErrors(res) {
if (res.status === 500) {
throw new Error('Sorry our servers are down, please try again later');
} else if (res.status === 404) {
throw new Error('Sorry, resource was not found');
} else if (res.status === 200) {
return res.json();
} else if (res.status === 201) {
return res.json();
} else if (res.status === 202) {
return res.json();
} else {
throw new Error('Something went wrong');
}
}
Then I moved on to creating an Error
Component to render to the page if there was an error... {!!this.state.error.length && <Error error={error} />}
. Error was a functional component that returned something simple, just a div with a red background, white text, and the error message inside. Sweet, everything is looking good... 15 minutes to go.
Because I was short on time at this point I couldn't intercept my network requests and write tests in Cypress to stub 404 and 500 errors so I went with a quick hack to throw a 404 and deleted the last letter from the URL, so now I was attempting to fetch from http://localhost:3001/api/v1/reservation
instead of http://localhost:3001/api/v1/reservations
I made the changes, checked out my other screen, hoping to see a nice 'Sorry, resource was not found' and saw...
HUH??
In the remaining few, stressful, minutes of the assessment, I googled the error message (to no avail), triple checked my syntax, imports, exports, and console.logged just about everything possible and found nothing amiss-- WHY wasn't my nice, user-friendly error message showing up on the page?
Unfortunately, three hours were up, I snuck that s
back into the URL, made a commit and pushed it up anyway. I sighed... despite pushing up a bug, I had, at least, gotten well past where I needed to be for the mid-mod.
I was still curious though, and I'm sure you are as well, what exactly does this cryptic error message mean?
_Errors_Error__WEBPACK_IMPORTED_MODULE_4__.default is not a constructor
After lunch I paired with a mentor here at Turing, dug into it some more and ended up stumbling upon the (now very obvious) answer... You can't use throw new Error
and name a component Error
in the same file.
Why not? Let me break it down into steps:
During the creation phase in my App component, the JS interpreter imports
Error from '../Error/Error
React runs ComponentDidMount(), which makes a fetch call. We end up inside of
checkForErrors
Because of my bad URL, the response status was 404, so the interpreter goes to block that includes
throw new Error('Sorry, resource was not found')
The JS interpreter sees the keyword
new
andError
and thinks to itself, "Nice, I know that an Error is, we imported that up top, let's make a new one of those!" It then skips off into Error.js where it finds a functional component, not a class component, and doesn't find a constructor.The confused JS interpreter says, "You said new and I didn't find a constructor so I don't know WTF you want me to do"
Would you like this error message instead?
So, why did this happen in the first place? I was rushing, and it explicitly wasn't an expectation of the mid-mod for us to move our fetch calls into a different folder/file, so I didn't. That means that everything CRUD-related and error-related was happening directly inside of App where my Error component was being imported. I wouldn't have seen that weird Webpack error if I had called my component Errors
, ErrorComponent
or Bananas
... or if I just followed best practices in the first place.
Long story short, slow is smooth and smooth is fast.