1

Im 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>
        </>
    )
}
Graunephar
  • 112
  • 1
  • 9
  • 1
    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. – thewildandy Mar 09 '23 at 15:25
  • @thewildandy If your comment was an answer I would accept it, I think its the answer I was looking for – Graunephar Apr 20 '23 at 08:04
  • let's fix that! – thewildandy Apr 20 '23 at 10:38

2 Answers2

1

If you simply want to redirect to another page, you can use the browser's location API.

Most likely, though, you'll want to call Astro using a fetch call to an endpoint, sending your form's data:

 <Box component="form" onSubmit={async (event) => {
    event.preventDefault();
    const formData = new FormData(event.target);
    const response = await fetch("/api/myEndpoint", {
        method: "POST",
        body: formData,
    });
}} noValidate sx={{mt: 1}}>
Jutanium
  • 421
  • 3
  • 16
  • I specifically want to do it from astro so I can use Astro.redirect(). Or ideally I would like to use the navigate method from astro-spa: https://github.com/RafidMuhymin/astro-spa – Graunephar Mar 06 '23 at 01:27
  • 1
    Can you explain why you want to do it this way? Astro pages (i.e. those with the .astro extension and assuming you are not using Astro's API-routes feature) are rendered in advance when you build your site, so one would assume they will essentially just perform a native JavaScript navigation under the hood (i.e. location.href = '/new-url'). – thewildandy Mar 09 '23 at 15:23
1

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.

thewildandy
  • 318
  • 2
  • 8