I am a new user testing out Astro. I currently have the following:
index.astro
---
import App from "../components/App.astro"
import KeycloakApp from "../components/KeycloakApp.astro";
const isAuthEnabled = true; //switch for local dev vs deployment
var isAuthenticated = true; //placeholder for keycloak component
if (!isAuthenticated) {
console.log("redirect")
return Astro.redirect('/Welcome');
}
---
{isAuthEnabled ? <KeycloakApp isAuthenticated={isAuthenticated} /> : <App />}
KeycloakApp.astro
---
import App from "../components/App.astro"
var {isAuthenticated} = Astro.props;
---
<!-- Keycloak wrapper of the regular App -->
<p><button id="flip">click me to flip isAuthenticated!</button></p>
<script>
function handleClick() {
console.log(isAuthenticated);
isAuthenticated = !{isAuthenticated};
console.log(isAuthenticated);
}
document.getElementById("flip").addEventListener("click", handleClick);
</script>
{isAuthenticated && <App />}
The console shows the following error when trying to click on the button:
Uncaught ReferenceError: isAuthenticated is not defined
at HTMLButtonElement.handleClick (KeycloakApp.astro:9:21)
How can I access the value of isAuthenticated inside my script? The name isAuthenticated cannot be found.
I am trying to reference the docs here
I am trying to look for a way to access astro props inside a script tag, though if not possible whatsoever, I might just fallback to using a react component with useStates
In Astro the frontmatter is only executed server-side so the props are not available inside your script
tag which is executed client side. To be able to use a prop inside the script
tag, you need to use define:vars
directive. See the Template Directives Reference on Astro documentation.
---
import App from "../components/App.astro"
var {isAuthenticated} = Astro.props;
---
<!-- Keycloak wrapper of the regular App -->
<p><button id="flip">click me to flip isAuthenticated!</button></p>
<script define:vars={{isAuthenticated}}>
function handleClick() {
console.log(isAuthenticated);
isAuthenticated = !{isAuthenticated};
console.log(isAuthenticated);
}
document.getElementById("flip").addEventListener("click", handleClick);
</script>
{isAuthenticated && <App />}
The caveat is that when using define:vars
, Astro will also apply the is:inline
directive so your scripts won’t be bundled and will be inlined directly into the HTML.
If you don't want that behavior you could try using a data attribute on your button and read the value in your script tag. Something like (I haven't tested):
---
import App from "../components/App.astro"
var {isAuthenticated = false} = Astro.props;
---
<!-- Keycloak wrapper of the regular App -->
<p><button id="flip" data-authenticated={`${isAuthenticated}`}>click me to flip isAuthenticated!</button></p>
<script>
function handleClick(e) {
let isAuthenticated = Boolean(e.currentTarget.dataset.authenticated);
console.log(isAuthenticated);
isAuthenticated = !{isAuthenticated};
console.log(isAuthenticated);
e.currentTarget.dataset.authenticated = String(isAuthenticated);
}
document.getElementById("flip").addEventListener("click", handleClick);
</script>
{isAuthenticated && <App />}