GOOGLE ADS

miércoles, 20 de abril de 2022

Manera correcta de usar el controlador de forma de gancho de reacción con Autocompletar Material-UI

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

TLDR: necesita usar MUI Autocompletar con el controlador de forma de gancho de reacción sindefaultValue

Mi Autocompletecomponente personalizado toma un objeto con la estructura {_id:'', name: ''}, muestra el nombre y devuelve el_id cuando se selecciona una opción. El Autocompletefunciona 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 react-hook-form, configuré el setValuespara que sea el controlador onChangeen elAutocomplete y registré manualmente el componente de la useEffectsiguiente manera

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

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

A continuación, traté de usar el Controllercomponente from react-hook-formpara registrar correctamente el campo en el formulario y no usar el useEffectgancho

<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é el onChangecomponente Autocompletepara devolver el valor directamente, pero parece que no funciona.

Usar inputRef={register}en el <TextField/>no sería suficiente para mí porque quiero guardar el _idy no elname

AQUÍ hay una caja de arena de trabajo con los dos casos. El primero con useEffecty setValueen el Autocompleteque funciona. El segundo mi intento de usar el Controllercomponente

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 unico problema es que me sale un MUI Erroren la consola

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

He intentado configurar un defaultValuepara él, pero todavía 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Í

Any help is still very much appreciated


Solución del problema

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}
/>

controles del valor de retorno deuseForm(}

Tenga en cuenta que estoy pasando nullcomo defaultValueen mi caso, esta entrada no es necesaria. Si se va, defaultValuees posible que obtenga algunos errores de la biblioteca material-ui.

ACTUALIZAR:

Per Steve question in the comments, this is how I'm rendering the input, so that it checks for errors:

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

De donde errorses un objeto de react-hook-form's formMethods:

const { control, watch, errors, handleSubmit } = formMethods

No hay comentarios:

Publicar un comentario

Regla de Firestore para acceder a la generación de subcolección Permisos faltantes o insuficientes

Tengo problemas con las reglas de Firestore para permitir el acceso a algunos recursos en una subcolección. Tengo algunos requests document...