Home > front end >  Cannot access '____' before initialization useEffect
Cannot access '____' before initialization useEffect

Time:10-24

This is my register form, very basic, built with MUI and React-Hook-Form.

Stackblitz: https://stackblitz.com/edit/react-qmdlmz?file=src/App.js

I'm kindly asking if you can help me fix this error: Cannot access stateRegister before initialization.

import * as React from 'react';
import Grid from '@mui/material/Grid';
import Typography from '@mui/material/Typography';
import TextField from '@mui/material/TextField';
import FormControlLabel from '@mui/material/FormControlLabel';
import Checkbox from '@mui/material/Checkbox';
import propTypes from 'prop-types';
import { useForm } from 'react-hook-form';

export default function BasicForm(props) {
  const {
    register,
    formState: { errors },
    watch,
  } = useForm({
    mode: 'all',
  });

  React.useEffect(() => {
    props.stateOfRegister(stateRegister);
    const subscription = watch((value, { name, type }) =>
      console.log(value, name, type)
    );

    return () => subscription.unsubscribe();
  }, [watch, props, stateRegister]);           //error occure at this line

  console.log('errors: ', errors);
  const stateRegister = watch();
  console.log('s', stateRegister);

  return (
    <React.Fragment>
      <Typography variant="h6" gutterBottom>
        Register your informations
      </Typography>
      <Typography variant="caption" color="red" gutterBottom>
        All champs are required *
      </Typography>
      <Grid container spacing={3}>
        <Grid item xs={12}>
          <TextField
            required
            id="username"
            name="username"
            label="Username"
            fullWidth
            autoComplete="username"
            variant="standard"
            {...register('username', {
              required: 'Username is required',
              minLength: {
                value: 3,
                message: 'Username must be at least 3 characts long',
              },
              maxLength: {
                value: 30,
                message: 'Username must be at most 30 characts long',
              },
            })}
            helperText={errors.username?.message}
          />
        </Grid>
        <Grid item xs={12}>
          <TextField
            required
            id="login"
            name="login"
            label="Email"
            type="email"
            fullWidth
            autoComplete="email"
            variant="standard"
            {...register('login', {
              required: 'Email is required',
              pattern: {
                value:
                  /^(([^<>()[\]\\.,;:\s@"] (\.[^<>()[\]\\.,;:\s@"] )*)|(". "))@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\])|(([a-zA-Z\-0-9] \.) [a-zA-Z]{2,}))$/,
                message: 'Email must be valid',
              },
            })}
            helperText={errors.login?.message}
          />
        </Grid>
        <Grid item xs={12}>
          <TextField
            required
            id="password"
            name="password"
            label="Password"
            type="password"
            minLength="8"
            fullWidth
            autoComplete="password"
            variant="standard"
            {...register('password', {
              required: 'Password is required',
              pattern: {
                value:
                  /^(?=.*[0-9])(?=.*[!@#$%^&*.,])[a-zA-Z0-9!@#$%^&*.,]{6,16}$/,
                message:
                  'Password must contain At least 6 Characters, One Uppercase, One Lowercase, One Number and One Special Case Character',
              },
            })}
            helperText={errors.password?.message}
          />
          {stateRegister.password}
        </Grid>
        <Grid item xs={12}>
          <FormControlLabel
            control={
              <Checkbox color="secondary" name="saveLogin" value="yes" />
            }
            label="Keep me logged in"
          />
        </Grid>
      </Grid>
    </React.Fragment>
  );
}

BasicForm.propTypes = {
  stateOfRegister: propTypes.func,
};

CodePudding user response:

You should move const stateRegister = watch(); before useEffect, but I think it also carries other side-effects from watch(), so I'd suggest that you use useEffect to manage stateRegister as a state change instead.

//Add a new state with a default value `{}`
const [stateRegister, setStateRegister] = React.useState({});

  React.useEffect(() => {
    //update stateRegister with watch()
    const stateRegister = watch();
    setStateRegister(stateRegister);

    props.stateOfRegister(stateRegister);
    const subscription = watch((value, { name, type }) =>
      console.log(value, name, type)
    );

    return () => subscription.unsubscribe();
  }, []);

If you don't want to have a default value for stateRegister, you have to add a conditional rendering for stateRegister in JSX

{stateRegister && stateRegister.password}

Or

{stateRegister?.password}
  • Related