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

docs: Reverse recommendation for controlled inputs #1089

Merged
merged 4 commits into from
Jul 4, 2024
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
41 changes: 39 additions & 2 deletions content/en/guide/v10/forms.md
Original file line number Diff line number Diff line change
Expand Up @@ -29,10 +29,47 @@ A framework like Preact in contrast generally has a unidirectional data flow. Th
<input value={someValue} onInput={myEventHandler} />;
```

Generally, you should try to use _Controlled_ Components at all times. However, when building standalone Components or wrapping third-party UI libraries, it can still be useful to simply use your component as a mount point for non-preact functionality. In these cases, "Uncontrolled" Components are nicely suited to the task.

> One gotcha to note here is that setting the value to `undefined` or `null` will essentially become uncontrolled.

Generally, you should try to use _Uncontrolled_ Components whenever possible, the DOM is fully capable of handling `<input>`'s state. However, there are situations in which you might need to exert tighter control over the input value, in which case, _Controlled_ Components can be used.

To use controlled components in Preact, you will need to use [`refs`](/guide/v10/refs) to bridge the inherent gap between the DOM state and VDOM/Preact's state. Here's an example of how you might use a controlled component to limit the number of characters in an input field:

```jsx
// --repl
import { render } from "preact";
import { useState, useRef } from "preact/hooks";
// --repl-before
const Input = () => {
const [value, setValue] = useState('')
const inputRef = useRef()

const onInput = (e) => {
if (e.currentTarget.value.length <= 3) {
setValue(e.currentTarget.value)
} else {
const start = inputRef.current.selectionStart
const end = inputRef.current.selectionEnd
const diffLength = Math.abs(e.currentTarget.value.length - value.length)
inputRef.current.value = value
// Restore selection
inputRef.current.setSelectionRange(start - diffLength, end - diffLength)
}
}

return (
<>
<label>This input is limited to 3 characters: </label>
<input ref={inputRef} value={value} onInput={onInput} />
</>
);
}
// --repl-after
render(<Input />, document.getElementById("app"));
```

> For more information on controlled components in Preact, see [Controlled Inputs](https://www.jovidecroock.com/blog/controlled-inputs) by Jovi De Croock.

## Creating A Simple Form

Let's create a simple form to submit todo items. For this we create a `<form>`-Element and bind an event handler that is called whenever the form is submitted. We do a similar thing for the text input field, but note that we are storing the value in our class ourselves. You guessed it, we're using a _controlled_ input here. In this example it's very useful, because we need to display the input's value in another element.
Expand Down
3 changes: 2 additions & 1 deletion src/components/code-block/index.jsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import { useMemo } from 'preact/hooks';
import { Suspense } from 'preact/compat';
import { wrap } from 'comlink';
import { textToBase64 } from '../controllers/repl/query-encode.js';
import { useResource } from '../../lib/use-resource';

let prismWorker;
Expand Down Expand Up @@ -81,7 +82,7 @@ function HighlightedCodeBlock({ code, lang }) {
</Suspense>
</pre>
{repl && (
<a class="repl-link" href={`/repl?code=${encodeURIComponent(source)}`}>
<a class="repl-link" href={`/repl?code=${encodeURIComponent(textToBase64(source))}`}>
Comment on lines -84 to +85
Copy link
Member Author

Choose a reason for hiding this comment

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

Sorry, unrelated but missed in #1162 as we for some reason weren't calling btoa on this. Grep didn't find any other btoa references so I assumed we were all covered.

Run in REPL
</a>
)}
Expand Down