Phil Mckavity
Phil Mckavity

Reputation: 1

Hydration failure in Next.js while using React Bootstrap Form Component

I am implementing a simple login component using a Form component from react-bootstrap. I keep running into the error: "Error: Hydration failed because the initial UI does not match what was rendered on the server." I understand this happens when there is an incorrect nesting of HTML elements, and the error hints to this being the cause when it says "Did not expect server HTML to contain a <div> in <div>." The following is my code:

"use client"

import React, { useState } from 'react';
import { Form, Button, Container } from 'react-bootstrap';
import axios from 'axios';
import useStore from '../stores/useStore';

const Login = () => {
    const [email, setEmail] = useState('');
    const [password, setPassword] = useState('');
    const [error, setError] = useState('');
    const { setUser } = useStore();

    const handleLogin = async (event) => {
        event.preventDefault();
        try {
            const response = await axios.post('/api/signin', { email, password });
            const { token, user } = response.data;
            localStorage.setItem('token', token);
            setUser(user);
            window.location.href = '/home';
        } catch (err) {
            setError('Invalid email or password');
        }
    };

    return (
        <Container>
            <div>
                <h2>Login</h2>
                <h6>Please sign in to continue</h6>
                <Form onSubmit={handleLogin}>
                    <Form.Group controlId="formBasicEmail">
                        <Form.Label>Email address</Form.Label>
                        <Form.Control
                            type="email"
                            placeholder="E-mail address"
                            value={email}
                            onChange={(e) => setEmail(e.target.value)}
                            required
                        />
                    </Form.Group>

                    <Form.Group controlId="formBasicPassword">
                        <Form.Label>Password</Form.Label>
                        <Form.Control
                            type="password"
                            placeholder="Password"
                            value={password}
                            onChange={(e) => setPassword(e.target.value)}
                            required
                        />
                    </Form.Group>

                    {error && <p className="text-danger">{error}</p>}

                    <Button variant="primary" type="submit">
                        Login
                    </Button>
                </Form>
                <p className="signup-link">
                    New to us? <a href="/signup">Sign Up</a>
                </p>
            </div>
        </Container>
    );
};

export default Login;

I've gone through and commented out this component line by line and have identified a few items that seem to trigger this hydration error, those being the controlId in Form.Group, type in Form.Control, and value in Form.Control. Does anyone know why this occurs and what a solution or workaround might be?

Upvotes: 0

Views: 100

Answers (1)

Phil Mckavity
Phil Mckavity

Reputation: 1

For anyone looking for an answer, I have found a workaround. The dynamic import from next allows you to turn off ssr for specific components. I needed to use it on the component that is importing the Login component that I referred to in the initial question. So my code looks like the following:

import React from 'react';
import useStore from '../stores/useStore';
import Instructions from 'src/app/components/Introduction';
import dynamic from 'next/dynamic';

const Login = dynamic(() => import('../components/Login'), {
    ssr: false,
})


const Home = () => {
const { user, setUser } = useStore();

return(
    <>
        <h1>Welcome to Overtime Odds</h1>
        {user ? (
            <p className="mt-2">Logged in as {user.name}</p>
          ) : (
            <>
                <Login/>
                <Instructions/>
            </>
          )}
    </>
)
}

export default Home;

I think maybe these client-side styled-component libraries maybe don't mix well with next.js? Just my impression so far, this is my first time developing with next.js.

Upvotes: 0

Related Questions