Poincenot Common React
Poincenot Common React es una libreria de componentes genéricos de todo tipo escrita en React Typescript basada en el framework Material UI para Poincenot Tech Studio
Forms: React Hook Form
Instalación
npm install --save pcnt_common_react
React Hook Form
Ejemplo de uso de un formulario basado enimport React from 'react'
import {
FormGeneric,
FieldText,
FieldCheckbox,
FieldSelect,
} from 'pcnt_common_react';
const countryOptions = [
{ value: '', label: '' },
{ value: 'AR', label: 'Argentina' },
{ value: 'US', label: 'United States' },
{ value: 'ES', label: 'España' },
];
const UsersForm = () => {
const initialValues = {
username: '',
is_older_than_18: false,
country: '',
};
const validationSchema = yup.object().shape({
username: yup
.string()
// recordá agregarle la prop required en el campo
// correspondiente si el mismo es requerido.
.required('El campo nombre de usuario es requerido!'),
country: yup
.string()
});
const handleSubmit = (values) => {
return backend(values)
.then((success) => {
// acá podes mostrar un toast
// diciendo que todo salió bien!
console.log(success);
})
.catch((error) => {
// importante: FormGeneric toma
// un error de tipo string para
// mostrar un error al usuario final.
throw error.message;
})
};
return (
<FormGeneric
initialValues={initialValues}
validationSchema={validationSchema}
onSubmit={handleSubmit}
{}
>
<FieldText
name="username"
label="Username"
{ /*
gridProps para pasarle las props al wrapper de
Grid que envuelve al <FieldGeneric> ver API.
https://material-ui.com/api/grid/
*/ }
gridProps={{ xs: 4 }}
required
/>
<FieldCheckbox
name="is_older_than_18"
label="Is older than eighteen"
gridProps={{ xs: 4 }}
/>
<FieldSelect
name="country"
label="Country"
options={countryOptions}
gridProps={{ xs: 4 }}
/>
</FormGeneric>
);
}
export default UsersForm;
Ejemplo de uso de FieldGenericTextField
FieldGenericTextField sirve para wrappear aquellos componentes que renderizen internamente un TextField de Material UI. Ya sea el mismo TextField, AutoComplete, DatePicker, etc.
import React from 'react';
import {
KeyboardDatePicker,
KeyboardDatePickerProps,
MuiPickersUtilsProvider
} from '@material-ui/pickers';
import DateFnsUtils from '@date-io/date-fns';
import {
FieldGenericTextField,
IFieldGenericRenderProps,
IFieldGenericTextField,
} from './FieldGeneric';
type OmitKeyboardDatePickerProps = Omit<KeyboardDatePickerProps, "label" | "name" | "children" | "onChange" | "value">;
interface IFieldDatePicker extends IFieldGenericTextField, OmitKeyboardDatePickerProps {};
const FieldDatePicker = ({
name,
label,
fullWidth = true,
required,
gridProps,
...props
}:IFieldDatePicker) => {
return (
<FieldGenericTextField
name={name}
gridProps={gridProps}
required={required}
>
{({ controller, error }:IFieldGenericRenderProps) => (
<MuiPickersUtilsProvider utils={DateFnsUtils}>
<KeyboardDatePicker
value={controller.field.value}
label={label}
error={!!error}
required={required}
// usa el helperText que hereda de TextField
helperText={error}
margin='normal'
fullWidth={fullWidth}
onChange={(e) => controller.field.onChange(e)}
format='dd/MM/yyyy'
KeyboardButtonProps={{
'aria-label': 'change date'
}}
{...props}
/>
</MuiPickersUtilsProvider>
)}
</FieldGenericTextField>
);
};
export default FieldDatePicker;
Ejemplo de uso de FieldGenericCheckboxSwitchRadioButton
FieldGenericCheckboxSwitchRadioButton sirve para wrappear aquellos componentes que renderizen internamente componentes de valores booleanos como Checkbox, Switch o RadioButtons
import React from 'react';
import Switch, { SwitchProps } from '@material-ui/core/Switch';
import {
FieldGenericCheckboxSwitchRadioButton as FieldGeneric,
IFieldGenericCheckboxSwitchRadioButton as IFieldGeneric,
IFieldGenericRenderProps,
} from './FieldGeneric';
interface IFieldSwitch extends IFieldGeneric, Omit<SwitchProps, "name"> {};
// no incluye un helperText
const FieldSwitch = ({
name,
label,
gridProps = {},
...props
}:IFieldSwitch) => {
return (
<FieldGeneric
name={name}
label={label}
gridProps={gridProps}
formControlLabelProps={{
labelPlacement: 'end',
}}
>
{({ controller }:IFieldGenericRenderProps) => (
<Switch
checked={controller.field.value}
onChange={(e) => controller.field.onChange(e.target.checked)}
color='primary'
{...props}
/>
)}
</FieldGeneric>
);
};
export default FieldSwitch;
Ejemplo de uso de FieldGenericWithLabelAndHelperText
FieldGenericWithLabelAndHelperText sirve para wrappear aquellos componentes que no correspondan a ninguno de los casos descriptos arriba. Se puede utilizar para wrappear cualquier componente de cualquier tipo que no incluya un label o un helperText.
En el ejemplo de abajo se puede ver como usamos un componente de Editor de código al cual le pasamos el objeto controller del formulario a las props value y onChange para manejarlo de forma controlada, además manejamos el focus con onBlur y onFocus para mostrar el label de FieldGeneric focuseado cuando corresponda.
import React, { useState } from "react";
import {
FieldGenericWithLabelAndHelperText as FieldGeneric,
IFieldGenericRenderProps,
IFieldGenericWithLabelAndHelperText as IFieldGeneric
} from './FieldGeneric';
import { CodeEditor, IAceEditorProps } from '../..';
interface IFieldCodeEditor extends IFieldGeneric, Omit<IAceEditorProps, "name"> {
height?: string;
};
const FieldCodeEditor = ({
name,
label,
required,
gridProps,
height = '300px',
...props
}:IFieldCodeEditor) => {
const [focused, setFocused] = useState(false);
return (
<FieldGeneric
name={name}
gridProps={gridProps}
label={label}
required={required}
focused={focused}
>
{({ controller }:IFieldGenericRenderProps) => (
<CodeEditor
name={name}
onChange={(e) => controller.field.onChange(e)}
onFocus={() => setFocused(true)}
onBlur={() => setFocused(false)}
value={controller.field.value}
height={height}
{...props}
/>
)}
</FieldGeneric>
);
};
export default FieldCodeEditor;