diff --git a/docs/Inputs.md b/docs/Inputs.md index f8af3a0f548..4e264763913 100644 --- a/docs/Inputs.md +++ b/docs/Inputs.md @@ -774,6 +774,7 @@ const BoundedTextField = ({ name, label }: { name: string; label: string }) => { fieldState: { isTouched, invalid, error }, formState: { isSubmitted } } = useController({ name, defaultValue: '' }); + return ( , InputProps {} @@ -935,6 +936,51 @@ const { isDirty } = useFormState(); // ✅ const formState = useFormState(); // ❌ should deconstruct the formState ``` +## i18n + +In order to properly format the input's `helperText` and error messages from `useInput()`, custom inputs should make use of the react-admin component ``, which ensures that the text below the input returns consistently whether it's a string or a React component, and whether it's a simple message or an error. Importantly, react-admin messages from `useInput()` are passed through `useTranslate()` inside ``, which makes this component important for localization. + +```jsx +import TextField from '@mui/material/TextField'; +import { useInput, InputHelperText } from 'react-admin'; + +const BoundedTextField = (props: BoundedTextFieldProps) => { + const { onChange, onBlur, label, helperText, ...rest } = props; + const { + field, + fieldState: { isTouched, invalid, error }, + formState: { isSubmitted }, + isRequired, + } = useInput({ + onChange, + onBlur, + ...rest, + }); + + const renderHelperText = + helperText !== false || ((isTouched || isSubmitted) && invalid); + + return ( + + ) : null + } + required={isRequired} + {...rest} + /> + ); +}; +``` + ## Third-Party Components You can find components for react-admin in third-party repositories. diff --git a/docs/useInput.md b/docs/useInput.md index 946af029fbc..de524ef7a8a 100644 --- a/docs/useInput.md +++ b/docs/useInput.md @@ -62,7 +62,7 @@ import TextField from '@mui/material/TextField'; import { useInput, required } from 'react-admin'; const BoundedTextField = (props) => { - const { onChange, onBlur, ...rest } = props; + const { onChange, onBlur, label, ...rest } = props; const { field, fieldState: { isTouched, invalid, error }, @@ -73,13 +73,13 @@ const BoundedTextField = (props) => { // useInput will call the provided onChange and onBlur in addition to the default needed by react-hook-form. onChange, onBlur, - ...props, + ...rest, }); return ( { ); }; ``` - -**Reminder:** [react-hook-form's `formState` is wrapped with a Proxy](https://react-hook-form.com/docs/useformstate/#rules) to improve render performance and skip extra computation if specific state is not subscribed. So, make sure you deconstruct or read the `formState` before render in order to enable the subscription. - -```js -const { isDirty } = useFormState(); // ✅ -const formState = useFormState(); // ❌ should deconstruct the formState -``` - ## Usage with Material UI `