Empresas
Empregos
  • Sobre nós
  • Soluções
    • Publicação de vagas
      Publique sua vaga e receba candidatos qualificados em 48h.
    • Avaliações de candidatos
      Mais de 500 testes técnicos e psicológicos, mais anti-fraude.
    • Headhunting
      Busca executiva personalizada do início ao fim.
    • Folha de Pagamento + EOR
      Dispersão de folha e EOR em mais de 15 países da LATAM.
  • Preços
  • Empregos

0

144
Visualizações
Manera correcta de usar el controlador de forma de gancho de reacción con Autocompletar Material-UI

Estoy tratando de usar un componente Material-UI Autocomplete personalizado y conectarlo a react-hook-form .

TLDR: es necesario usar MUI Autocompletar con el controlador de forma de gancho de reacción sin defaultValue

Mi componente Autocomplete personalizado toma un objeto con la estructura {_id:'', name: ''} , muestra el nombre y devuelve el _id cuando se selecciona una opción. El Autocomplete funciona bien.

 <Autocomplete options={options} getOptionLabel={option => option.name} getOptionSelected={(option, value) => option._id === value._id} onChange={(event, newValue, reason) => { handler(name, reason === 'clear' ? null : newValue._id); }} renderInput={params => <TextField {...params} {...inputProps} />} />

Para que funcione con react-hook-form configuré setValues para que sea el controlador de onChange en Autocomplete y registré manualmente el componente en un useEffect de la siguiente manera

 useEffect(() => { register({ name: "country1" }); },[]);

Esto funciona bien, pero me gustaría no tener el gancho useEffect y simplemente hacer uso del registro de alguna manera directamente.

A continuación, traté de usar el componente Controller de react-hook-form para registrar correctamente el campo en el formulario y no usar el gancho useEffect

 <Controller name="country2" as={ <Autocomplete options={options} getOptionLabel={option => option.name} getOptionSelected={(option, value) => option._id === value._id} onChange={(event, newValue, reason) => reason === "clear" ? null : newValue._id } renderInput={params => ( <TextField {...params} label="Country" /> )} /> } control={control} />

Cambié onChange en el componente Autocomplete para devolver el valor directamente, pero parece que no funciona.

Usar inputRef={register} en <TextField/> no me serviría porque quiero guardar el _id y no el name

AQUÍ hay una caja de arena de trabajo con los dos casos. El primero con useEffect y setValue en el Autocomplete que funciona. El segundo mi intento de usar el componente Controller

Cualquier ayuda es apreciada.

LE

Después del comentario de Bill con el sandbox de trabajo de MUI Autocompletar, logré obtener un resultado funcional

 <Controller name="country" as={ <Autocomplete options={options} getOptionLabel={option => option.name} getOptionSelected={(option, value) => option._id === value._id} renderInput={params => <TextField {...params} label="Country" />} /> } onChange={([, { _id }]) => _id} control={control} />

El único problema es que me sale un MUI Error en la consola

Material-UI: un componente está cambiando el estado de valor no controlado de Autocompletar para ser controlado.

Intenté establecer un defaultValue para él, pero aún se comporta así. Además, no me gustaría establecer un valor predeterminado de la matriz de opciones debido al hecho de que estos campos en el formulario no son obligatorios.

El sandbox actualizado AQUÍ

Cualquier ayuda sigue siendo muy apreciada.

over 4 years ago · Santiago Trujillo
4 Respostas
Responde à pergunta

0

Entonces, arreglé esto. Pero reveló lo que creo que es un error en Autocompletar.

Primero... específicamente para su problema, puede eliminar el MUI Error agregando un valor predeterminado al <Controller> . Pero eso fue solo el comienzo de otra ronda o problemas.

El problema es que a las funciones getOptionLabel , getOptionSelected y onChange a veces se les pasa el valor (es decir, el _id en este caso) y, a veces, se les pasa la estructura de opciones, como era de esperar.

Aquí está el código que finalmente se me ocurrió:

 import React from "react"; import { useForm, Controller } from "react-hook-form"; import { TextField } from "@material-ui/core"; import { Autocomplete } from "@material-ui/lab"; import { Button } from "@material-ui/core"; export default function FormTwo({ options }) { const { register, handleSubmit, control } = useForm(); const getOpObj = option => { if (!option._id) option = options.find(op => op._id === option); return option; }; return ( <form onSubmit={handleSubmit(data => console.log(data))}> <Controller name="country" as={ <Autocomplete options={options} getOptionLabel={option => getOpObj(option).name} getOptionSelected={(option, value) => { return option._id === getOpObj(value)._id; }} renderInput={params => <TextField {...params} label="Country" />} /> } onChange={([, obj]) => getOpObj(obj)._id} control={control} defaultValue={options[0]} /> <Button type="submit">Submit</Button> </form> ); }
over 4 years ago · Santiago Trujillo Relatório

0

La respuesta aceptada (probablemente) funciona para la versión con errores de Autocompletar. Creo que el error se solucionó algún tiempo después, por lo que la solución se puede simplificar un poco.

Esta es una referencia/codesandbox muy útil cuando se trabaja con react-hook-form y material-ui: https://codesandbox.io/s/react-hook-form-controller-601-j2df5 ?

Desde el enlace anterior, modifiqué el ejemplo de Autocompletar:

 import TextField from '@material-ui/core/TextField'; import Autocomplete from '@material-ui/lab/Autocomplete'; const ControlledAutocomplete = ({ options = [], renderInput, getOptionLabel, onChange: ignored, control, defaultValue, name, renderOption }) => { return ( <Controller render={({ onChange, ...props }) => ( <Autocomplete options={options} getOptionLabel={getOptionLabel} renderOption={renderOption} renderInput={renderInput} onChange={(e, data) => onChange(data)} {...props} /> )} onChange={([, data]) => data} defaultValue={defaultValue} name={name} control={control} /> ); }

Con el uso:

 <ControlledAutocomplete control={control} name="inputName" options={[{ name: 'test' }]} getOptionLabel={(option) => `Option: ${option.name}`} renderInput={(params) => <TextField {...params} label="My label" margin="normal" />} defaultValue={null} />

el control es del valor de retorno de useForm(}

Tenga en cuenta que estoy pasando null como valor defaultValue ya que en mi caso esta entrada no es necesaria. Si deja defaultValue , es posible que obtenga algunos errores de la biblioteca material-ui.

ACTUALIZAR:

Según la pregunta de Steve en los comentarios, así es como represento la entrada, para que verifique si hay errores:

 renderInput={(params) => ( <TextField {...params} label="Field Label" margin="normal" error={errors[fieldName]} /> )}

Donde errors es un objeto de formMethods de react-hook-form :

 const { control, watch, errors, handleSubmit } = formMethods
over 4 years ago · Santiago Trujillo Relatório

0

En lugar de usar el controlador, con la ayuda de register, setValue de useForm y value, onChange of Autocompletar podemos lograr el mismo resultado.

 const [selectedCaste, setSelectedCaste] = useState([]); const {register, errors, setValue} = useForm(); useEffect(() => { register("caste"); }, [register]); return ( <Autocomplete multiple options={casteList} disableCloseOnSelect value={selectedCaste} onChange={(_, values) => { setSelectedCaste([...values]); setValue("caste", [...values]); }} getOptionLabel={(option) => option} renderOption={(option, { selected }) => ( <React.Fragment> <Checkbox icon={icon} checkedIcon={checkedIcon} style={{ marginRight: 8 }} checked={selected} /> {option} </React.Fragment> )} style={{ width: "100%" }} renderInput={(params) => ( <TextField {...params} id="caste" error={!!errors.caste} helperText={errors.caste?.message} variant="outlined" label="Select caste" placeholder="Caste" /> )} /> );
over 4 years ago · Santiago Trujillo Relatório

0

import { Button } from "@material-ui/core"; import Autocomplete from "@material-ui/core/Autocomplete"; import { red } from "@material-ui/core/colors"; import Container from "@material-ui/core/Container"; import CssBaseline from "@material-ui/core/CssBaseline"; import { makeStyles } from "@material-ui/core/styles"; import TextField from "@material-ui/core/TextField"; import AdapterDateFns from "@material-ui/lab/AdapterDateFns"; import LocalizationProvider from "@material-ui/lab/LocalizationProvider"; import React, { useEffect, useState } from "react"; import { Controller, useForm } from "react-hook-form"; export default function App() { const [itemList, setItemList] = useState([]); // const classes = useStyles(); const { control, handleSubmit, setValue, formState: { errors } } = useForm({ mode: "onChange", defaultValues: { item: null } }); const onSubmit = (formInputs) => { console.log("formInputs", formInputs); }; useEffect(() => { setItemList([ { id: 1, name: "item1" }, { id: 2, name: "item2" } ]); setValue("item", { id: 3, name: "item3" }); }, [setValue]); return ( <LocalizationProvider dateAdapter={AdapterDateFns}> <Container component="main" maxWidth="xs"> <CssBaseline /> <form onSubmit={handleSubmit(onSubmit)} noValidate> <Controller control={control} name="item" rules={{ required: true }} render={({ field: { onChange, value } }) => ( <Autocomplete onChange={(event, item) => { onChange(item); }} value={value} options={itemList} getOptionLabel={(item) => (item.name ? item.name : "")} getOptionSelected={(option, value) => value === undefined || value === "" || option.id === value.id } renderInput={(params) => ( <TextField {...params} label="items" margin="normal" variant="outlined" error={!!errors.item} helperText={errors.item && "item required"} required /> )} /> )} /> <button onClick={() => { setValue("item", { id: 1, name: "item1" }); }} > setValue </button> <Button type="submit" fullWidth size="large" variant="contained" color="primary" // className={classes.submit} > submit </Button> </form> </Container> </LocalizationProvider> ); }
over 4 years ago · Santiago Trujillo Relatório
Responde à pergunta
Encontrar trabalhos remotos

Descubra a nova forma de encontrar um emprego!

melhores empregos
Principais categorias de trabalho
Empresas
Postar vaga Preços Comercial
Jurídico
Termos e Condições Política de privacidade
© 2026 PeakU Inc. All Rights Reserved.
Andres GPT
Recomende algumas ofertas para mim
Preciso de ajuda