Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Doc] Add i18n InputHelpterText section to Inputs/useInputs docs #9315

Merged
merged 6 commits into from
Sep 28, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
48 changes: 47 additions & 1 deletion docs/Inputs.md
Original file line number Diff line number Diff line change
Expand Up @@ -774,6 +774,7 @@ const BoundedTextField = ({ name, label }: { name: string; label: string }) => {
fieldState: { isTouched, invalid, error },
formState: { isSubmitted }
} = useController({ name, defaultValue: '' });

return (
<TextField
{...field}
Expand Down Expand Up @@ -832,7 +833,7 @@ import { useInput, required, InputProps } from "react-admin";
interface BoundedTextFieldProps
extends Omit<
TextFieldProps,
"label" | "helperText" | "onChange" | "onBlur" | "type" | "defaultValue"
"label" | "onChange" | "onBlur" | "type" | "defaultValue"
>,
InputProps {}

Expand Down Expand Up @@ -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 `<InputHelperText>`, 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 `<InputHelperText>`, 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 (
<TextField
{...field}
label={label}
error={(isTouched || isSubmitted) && invalid}
helperText={
renderHelperText ? (
<InputHelperText
touched={isTouched || isSubmitted}
error={error?.message}
helperText={helperText}
/>
) : null
}
required={isRequired}
{...rest}
/>
);
};
```

## Third-Party Components

You can find components for react-admin in third-party repositories.
Expand Down
29 changes: 17 additions & 12 deletions docs/useInput.md
Original file line number Diff line number Diff line change
Expand Up @@ -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 },
Expand All @@ -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 (
<TextField
{...field}
label={props.label}
label={label}
error={(isTouched || isSubmitted) && invalid}
helperText={(isTouched || isSubmitted) && invalid ? error : ''}
required={isRequired}
Expand All @@ -99,14 +99,6 @@ const LatLngInput = props => {
);
};
```

**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
```

Comment on lines -102 to -109
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I believe we should keep this one. @fzaninotto?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It's true that the reminder is mentioned twice in this chapter. I'd create a dedicated section explaining how to read the form state, and removing the reminder from the two sections avout TextField and Select.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@djhi Do you want to do it or should I? Rock paper scissors?

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🪨 That's not really related to your PR so if you don't, we'll open a new PR for that.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm on it then, after all, I broached it by removing the repeated section.

## Usage with Material UI `<Select>`

```jsx
Expand Down Expand Up @@ -154,9 +146,22 @@ const PersonEdit = () => (
);
```

**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.
**Tip**: Remember to use react-admin's `<InputHelperText>` component in custom inputs to properly translate and render messages and errors coming from `useInput()`.

## Important note about formState

[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
```

This pattern should be followed when writing a custom input with `useInput()`.

```jsx
const { formState: { isSubmitted }} = useInput(props); // ✅

const { formState } = useInput(props);
const submitted = formState.isSubmitted; // ❌
```