Search code examples
reactjsastrojs

Triggering TypeScript / JavaScript in Astro from React form in onSubmit


I'm experimenting with Astro and trying to create a login form on my Astro page. I want to use MUI components in React for my form. At the same time when the form in submitted I want to trigger Astro.redirect('/some-page'). I know from the docs that:

You can pass a function as a prop to a framework component, but it only works during server rendering. If you try to use the function in a hydrated component (for example, as an event handler), an error will occur.

This is because functions can’t be serialized (transferred from the server to the client) by Astro.

So my question is: Is it possible to trigger a redirect in astro from a function running when a react from is submitted?

And if not, how can I redirect in from the react component?

For good measure I have included my code below:

My Astro page looks like this

<Layout title="Log in">
<main>
    <div class="container box">
        <LoginFormReact client:only="react"/>
    </div>
</main>

And this is the content of LoginFormReact:

import Avatar from '@mui/material/Avatar';
import CssBaseline from '@mui/material/CssBaseline';
import LoginCheckbox from './LoginCheckBox'
import Grid from '@mui/material/Grid';
import Box from '@mui/material/Box';
import Typography from '@mui/material/Typography';
import Container from '@mui/material/Container';
import TextField from '@mui/material/TextField';
import Button from '@mui/material/Button';
import {setUser} from "../../auth/authStore";

export default function LoginFormReact() {


    return (
        <>
            <Container component={"main"} maxWidth={"xs"}>
                <CssBaseline/>
                <Box
                    sx={{
                        marginTop: 8,
                        display: 'flex',
                        flexDirection: 'column',
                        alignItems: 'center',
                    }}
                >
                    <Avatar sx={{m: 1, bgcolor: 'secondary.main'}}>
                    </Avatar>
                    <Typography component="h1" variant="h5">
                        Sign in
                    </Typography>
                    <Box component="form" onSubmit={async (event) => {
                        event.preventDefault();
                        //Here I can do all the js stuff i want like storing the user object. 
                        //This is also where I want to call redirect and or call astro
                    }} noValidate sx={{mt: 1}}>
                        <TextField
                            margin="normal"
                            required
                            fullWidth
                            id="email"
                            label="Email Address"
                            name="email"
                            autoComplete="email"
                            autoFocus
                        />
                        <TextField
                            margin="normal"
                            required
                            fullWidth
                            name="password"
                            label="Password"
                            type="password"
                            id="password"
                            autoComplete="current-password"
                        />
                        <LoginCheckbox/>
                        <Button
                            type="submit"
                            fullWidth
                            variant="contained"
                            sx={{mt: 3, mb: 2}}
                        >
                            Sign In
                        </Button>
                        <Grid container>
                            <Grid item xs>
                                <a href="#">
                                    Forgot password?
                                </a>
                            </Grid>
                            <Grid item>
                                <a href="#">
                                    {"Don't have an account? Sign Up"}
                                </a>
                            </Grid>
                        </Grid>
                    </Box>
                </Box>
            </Container>
        </>
    )
}

Solution

  • The answer depends on where your form submission will be handled. If you handle it in a React component, you can use location.href or location.replace. If you submit to a .astro page, that page will have access to Astro.redirect. Bear in mind .astro pages are pre-rendered, since Astro is a static site generator. The exception being if you're using Astro's API Routes feature.