It turns out I was completely barking up the wrong tree with my original answer.
The real issue you're running into is that on initial render, contact.error is falsy and contact.data is falsy. Since you don't reference their value anywhere on the page, the engine doesn't know it needs to recalculate their values.
If you simply reference their values in the view (not just in the template tag) as seen here:
<template>
<template if:true={contact.data}>
<p>{contact.data} Contact Details</p>
</template>
<template if:true={contact.error}>
<p>{contact.error} Error Message</p>
</template>
</template>
Everything will start rendering and re-rendering as expected.
The only thing on your controller code is I hardcoded an Id.
import { LightningElement, api, wire } from "lwc";
import { getRecord } from "lightning/uiRecordApi";
import FIRSTNAME_FIELD from "@salesforce/schema/Contact.FirstName";
const fields = [FIRSTNAME_FIELD];
export default class GetContact extends LightningElement {
//@api recordId;
//fake id
recordId = "fake";
@wire(getRecord, { recordId: "$recordId", fields })
contact;
}
Referencing your desired values in getters as seen in the documentation at https://developer.salesforce.com/docs/component-library/documentation/en/48.0/lwc/reference_wire_adapters_record will also cause things to start re-rendering as expected.
For example:
JS:
import { LightningElement, api, wire } from "lwc";
import { getRecord } from "lightning/uiRecordApi";
import FIRSTNAME_FIELD from "@salesforce/schema/Contact.FirstName";
const fields = [FIRSTNAME_FIELD];
export default class GetContact extends LightningElement {
//@api recordId;
//fake id
recordId = "fake";
@wire(getRecord, { recordId: "$recordId", fields })
contact;
//the engine now knows to track this value since I referenced it in a getter
//even though I never use it on the page
get error(){
return this.contact.error;
}
//the engine now knows to track this value since I referenced it in a getter
//even though I never use it on the page
get data(){
return this.contact.data;
}
}
HTML:
<template>
<template if:true={contact.data}>
<p>Contact Details</p>
</template>
<template if:true={contact.error}>
<p>Error Message</p>
</template>
</template>
{contact.error.message}
or{contact.error.body.message}
?{contact.error}
is always undefined in the above example.