rocketseat-content / youtube-next-auth-jwt

169 stars 78 forks source link

Como colocar o spreadoperator do register se meu input é um componente? #2

Open maykelesser opened 2 years ago

maykelesser commented 2 years ago

Seguindo o tutorial do Youtube, me deparei com uma situação: Se eu uso o input do HTML mesmo, funciona. Porém, em meu front-end, eu utilizo um componente Input customizado. No fim, ele gera um HTML normal. Porém, quando passo o {...register('email')}, ao executar o handleSignIn, ele me retorna undefined.

Não sei como proceder, nem como colocar este spread para ser lido no meu componente.

<Input {...register('email')} autofocus='true' className='mb-3' size='md' type='email' name='email' placeholder={translation('content.form.login.placeholder')} />
<Input {...register('password')} className='mb-3' size='md' type='password' name='password' placeholder={translation('content.form.password.placeholder')} />
// * Render
export default function Input(props){

    console.log(props.ref);

    let inputClasses = '';

    // * Size
    if(props.size){
        switch(props.size){
            case 'md':
                inputClasses += ' input-md ';
            break;
            case 'lg':
                inputClasses += ' input-lg ';
            break;
            case 'xl':
                inputClasses += ' input-xl ';
            break;
        }
    }
    else{
        inputClasses += ' input-base ';
    }

    return (
        <div className='form-control'>
            <input onBlur={props.onBlur} className={inputClasses + props.className} onKeyPress={props.onKeyPress} onChange={props.onChange} type={props.type} defaultValue={props.value} name={props.name} min={props.min} max={props.max} placeholder={props.placeholder} required={props.required} />
            {((props.subtitle) ? <p>{props.subtitle}</p> : '')}
        </div>
    )
}
lima-pedro commented 2 years ago

Fala Mayk , beleza ?

Cara eu li teu comentário, e achei uma solução aqui. Não sei se é a melhor porém pra mim funcionou, vamos lá:

Primeiro criei um componente chamado InputEmail com o seguinte código:

export default function InputEmail({ register }) {
  return (
    <div>
      <label htmlFor="email-address" className="sr-only">
        Email address
      </label>

      <input
          {...register("email")}
          id="email-address"
          name="email"
          type="email"
          autoComplete="email"
          required
          className="appearance-none rounded-none relative block w-full px-3 py-2 border border-gray-300 placeholder-gray-500 text-gray-900 rounded-t-md focus:outline-none focus:ring-indigo-500 focus:border-indigo-500 focus:z-10 sm:text-sm"
          placeholder="Email address"
        />
    </div>
  );
}

Eu realmente apenas copiei a div que já existia na index com o campo do e-mail, adicionei nele uma prop chamada register pra receber a função do useForm.

Em seguida eu usei esse componente lá na index e ai que vem o pulo do gato (rs) , coloquei a função register do useForm como uma props do componente:

<InputEmail register={ register } />

Dessa forma, quando lá no componente o dado for alterado, executa o register do useForm que está lá na index.

Lá no seu código ao invés de fazer o spread direto no componente customizado "Input", você coloca um nome pra props:

<Input inputRegister={register} autofocus='true' className='mb-3' size='md' type='email' name='email' placeholder={translation('content.form.login.placeholder')} />

Dai no seu componente customizado vc recebe props.inputRegister, assim:

export default function Input(props) {
  console.log(props.ref);

  let inputClasses = "";

  // * Size
  if (props.size) {
    switch (props.size) {
      case "md":
        inputClasses += " input-md ";
        break;
      case "lg":
        inputClasses += " input-lg ";
        break;
      case "xl":
        inputClasses += " input-xl ";
        break;
    }
  } else {
    inputClasses += " input-base ";
  }

  return (
    <div className="form-control">
      <input
        {...props.inputRegister('email')}
        onBlur={props.onBlur}
        className={inputClasses + props.className}
        onKeyPress={props.onKeyPress}
        onChange={props.onChange}
        type={props.type}
        defaultValue={props.value}
        name={props.name}
        min={props.min}
        max={props.max}
        placeholder={props.placeholder}
        required={props.required}
      />
      {props.subtitle ? <p>{props.subtitle}</p> : ""}
    </div>
  );
}

Não sei se te ajuda ou se foi isso que perguntou, mas espero ter ajudado!

Abraço!

gustaelesbao commented 1 year ago

Eu tive esse problema, para resolve isso você precisa dar acesso ao input via ForwardRef, pois o react-hook-form acessa o component via ref, um exemplo do seu caso usando ForwardRef:

export const InputEmail = forwardRef<HTMLInputElement, InputHTMLAttributes>((props, ref) => { return (

); });