I'm creating a React component which is intended to check for updates to a privacy policy page, based on whether the page is cached. I'm having two issues -
The Code
//Set the state to undefined initial, it'll
const [ppChanged, setPPStatus] = useState(undefined);
function checkPrivacyPolicyChanged(url) {
try {
fetch(url)
.then(
response => {
console.log("Response: ", response)
if (response.ok && response.status !== 304) {
//If the response code is 200-299 (ok status), and isn't cached (as indicated by status 304)
//Tell the component that the privacy policy has had changes since the user last saw it
setPPStatus(true);
} else if (response.status == 304) {
setPPStatus(false);
} else {
console.log(response);
}
},
//Error handling
error => {throw Error(error)}
)
}
catch(err) {
console.log(err)
}
}
//If we haven't determined the privacy policy state yet, check for it. (Using manifest.json for testing purposes)
if (ppChanged == undefined) {
checkPrivacyPolicyChanged("/manifest.json");
}
let color = "green";
//If a change to the privacy policy is detected, give a visual cue
if (ppChanged) {color = "purple"};
return(
<div style={{color}}>
{props.children}
</div>
);
}
The fetch standard describes this behaviour here.
- If response is null, then:
See statusses for a description about null body status
which are statusses that are 101
, 204
, 205
, or 304
.
10.4 If the revalidatingFlag is set and forwardResponse’s status is 304, then:
10.4.1 Update storedResponse’s header list using forwardResponse’s header list, as per the "Freshening Stored Responses upon Validation" chapter of HTTP Caching. [HTTP-CACHING]
This updates the stored response in cache as well.
10.4.2 Set response to storedResponse.
What this means is that the 200
status code comes from the response your browser has previously stored and is serving because it received a 304
. This makes sense, because the browser wouldn't be able to give you a response unless it queried the resource again (which is what is trying to be avoided with this 304 - Not modified
status).
You could keep track of one of the following headers of the request instead and compare these to a previously stored value:
As mentionned in the comments, the solution to this is to use the useEffect-hook.
useEffect(() => {
...
}, []); // Note the empty dependency array ensures that this code will only be executed once during the lifetime of this component.
The reason why this is needed is because during the rendering, this function will be executed more than once (for example, to update the state after a call to setPPStatus
).
When this function is re-executed, if the update hasn't occured yet, the if (ppChanged == undefined)
-block would be executed multiple times and therefor trigger multiple API calls.
By using the useEffect
-hook with an empty dependency array, you ensure that this code will only be executed once.