Browse Source

[Beta] react-dom: Components (#5383)

* <input>

* Fix typo

* tweak

* separate props

* reword

* typos

* compress

* tweaks

* Add more

* more

* shorter

* twk

* more readable

* fix

* oops

* oops

* <textarea>

* <progress>

* <select>, <progress>

* upd

* <option>

* wip common

* wip

* more

* Fix onSelect desc

* index

* stub events

* events

* twk

* all events
main
dan 2 years ago
committed by GitHub
parent
commit
d981e00db8
No known key found for this signature in database GPG Key ID: 4AEE18F83AFDEB23
  1. 2
      beta/src/components/Breadcrumbs.tsx
  2. 3
      beta/src/components/MDX/ConsoleBlock.tsx
  3. 3
      beta/src/components/MDX/Sandpack/Console.tsx
  4. 2
      beta/src/components/MDX/Sandpack/SandpackRoot.tsx
  5. 1180
      beta/src/content/apis/react-dom/components/common.md
  6. 263
      beta/src/content/apis/react-dom/components/index.md
  7. 595
      beta/src/content/apis/react-dom/components/input.md
  8. 80
      beta/src/content/apis/react-dom/components/option.md
  9. 70
      beta/src/content/apis/react-dom/components/progress.md
  10. 385
      beta/src/content/apis/react-dom/components/select.md
  11. 423
      beta/src/content/apis/react-dom/components/textarea.md
  12. 4
      beta/src/content/learn/manipulating-the-dom-with-refs.md
  13. 33
      beta/src/sidebarAPIs.json

2
beta/src/components/Breadcrumbs.tsx

@ -10,7 +10,7 @@ function Breadcrumbs() {
const {breadcrumbs} = useRouteMeta();
if (!breadcrumbs) return null;
return (
<div className="flex">
<div className="flex flex-wrap">
{breadcrumbs.map(
(crumb, i) =>
crumb.path && (

3
beta/src/components/MDX/ConsoleBlock.tsx

@ -58,7 +58,8 @@ function ConsoleBlock({level = 'error', children}: ConsoleBlockProps) {
className={cn(
'flex px-4 pt-4 pb-6 items-center content-center font-mono text-code rounded-b-md',
{
'bg-red-30 text-red-40 bg-opacity-10': level === 'error',
'bg-red-30 text-red-50 dark:text-red-30 bg-opacity-5':
level === 'error',
'bg-yellow-5 text-yellow-50': level === 'warning',
'bg-gray-5 text-secondary dark:text-secondary-dark':
level === 'info',

3
beta/src/components/MDX/Sandpack/Console.tsx

@ -109,6 +109,9 @@ export const SandpackConsole = ({visible}: {visible: boolean}) => {
setLogs((prev) => {
const newLogs = message.log
.filter((consoleData) => {
if (!consoleData.method) {
return false;
}
if (
typeof consoleData.data[0] === 'string' &&
consoleData.data[0].indexOf('The above error occurred') !== -1

2
beta/src/components/MDX/Sandpack/SandpackRoot.tsx

@ -74,7 +74,7 @@ function SandpackRoot(props: SandpackProps) {
files['/styles.css'] = {
code: [sandboxStyle, files['/styles.css']?.code ?? ''].join('\n\n'),
hidden: true,
hidden: !files['/styles.css']?.visible,
};
return (

1180
beta/src/content/apis/react-dom/components/common.md

File diff suppressed because it is too large

263
beta/src/content/apis/react-dom/components/index.md

@ -0,0 +1,263 @@
---
title: "react-dom: Components"
---
<Intro>
React supports all of the browser built-in [HTML](https://developer.mozilla.org/en-US/docs/Web/HTML/Element) and [SVG](https://developer.mozilla.org/en-US/docs/Web/SVG/Element) components.
</Intro>
<InlineToc />
---
## Common components {/*common-components*/}
All of the built-in browser components support some props and events.
* [Common components (e.g. `<div>`)](/apis/react-dom/components/common)
This includes React-specific props like `ref` and `dangerouslySetInnerHTML`.
---
## Form components {/*form-components*/}
These built-in browser components accept user input:
* [`<input>`](/apis/react-dom/components/input)
* [`<select>`](/apis/react-dom/components/select)
* [`<textarea>`](/apis/react-dom/components/textarea)
They are special in React because passing the `value` prop to them makes them *[controlled.](/apis/react-dom/components/input#controlling-an-input-with-a-state-variable)*
---
## All HTML components {/*all-html-components*/}
React supports all built-in browser HTML components. This includes:
* [`<aside>`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/aside)
* [`<audio>`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/audio)
* [`<b>`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/b)
* [`<base>`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/base)
* [`<bdi>`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/bdi)
* [`<bdo>`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/bdo)
* [`<blockquote>`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/blockquote)
* [`<body>`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/body)
* [`<br>`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/br)
* [`<button>`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/button)
* [`<canvas>`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/canvas)
* [`<caption>`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/caption)
* [`<cite>`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/cite)
* [`<code>`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/code)
* [`<col>`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/col)
* [`<colgroup>`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/colgroup)
* [`<data>`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/data)
* [`<datalist>`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/datalist)
* [`<dd>`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/dd)
* [`<del>`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/del)
* [`<details>`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/details)
* [`<dfn>`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/dfn)
* [`<dialog>`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/dialog)
* [`<div>`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/div)
* [`<dl>`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/dl)
* [`<dt>`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/dt)
* [`<em>`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/em)
* [`<embed>`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/embed)
* [`<fieldset>`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/fieldset)
* [`<figcaption>`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/figcaption)
* [`<figure>`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/figure)
* [`<footer>`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/footer)
* [`<form>`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/form)
* [`<h1>`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/h1)
* [`<head>`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/head)
* [`<header>`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/header)
* [`<hgroup>`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/hgroup)
* [`<hr>`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/hr)
* [`<html>`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/html)
* [`<i>`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/i)
* [`<iframe>`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/iframe)
* [`<img>`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/img)
* [`<input>`](/apis/react-dom/components/input)
* [`<ins>`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/ins)
* [`<kbd>`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/kbd)
* [`<label>`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/label)
* [`<legend>`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/legend)
* [`<li>`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/li)
* [`<link>`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/link)
* [`<main>`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/main)
* [`<map>`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/map)
* [`<mark>`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/mark)
* [`<menu>`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/menu)
* [`<meta>`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/meta)
* [`<meter>`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/meter)
* [`<nav>`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/nav)
* [`<noscript>`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/noscript)
* [`<object>`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/object)
* [`<ol>`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/ol)
* [`<optgroup>`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/optgroup)
* [`<option>`](/apis/react-dom/components/option)
* [`<output>`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/output)
* [`<p>`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/p)
* [`<picture>`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/picture)
* [`<pre>`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/pre)
* [`<progress>`](/apis/react-dom/components/progress)
* [`<q>`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/q)
* [`<rp>`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/rp)
* [`<rt>`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/rt)
* [`<ruby>`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/ruby)
* [`<s>`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/s)
* [`<samp>`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/samp)
* [`<script>`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/script)
* [`<section>`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/section)
* [`<select>`](/apis/react-dom/components/select)
* [`<slot>`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/slot)
* [`<small>`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/small)
* [`<source>`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/source)
* [`<span>`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/span)
* [`<strong>`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/strong)
* [`<style>`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/style)
* [`<sub>`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/sub)
* [`<summary>`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/summary)
* [`<sup>`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/sup)
* [`<table>`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/table)
* [`<tbody>`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/tbody)
* [`<td>`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/td)
* [`<template>`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/template)
* [`<textarea>`](/apis/react-dom/components/textarea)
* [`<tfoot>`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/tfoot)
* [`<th>`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/th)
* [`<thead>`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/thead)
* [`<time>`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/time)
* [`<title>`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/title)
* [`<tr>`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/tr)
* [`<track>`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/track)
* [`<u>`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/u)
* [`<ul>`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/ul)
* [`<var>`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/var)
* [`<video>`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/video)
* [`<wbr>`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/wbr)
<Note>
Similar to the [DOM standard,](https://developer.mozilla.org/en-US/docs/Web/API/Document_Object_Model) React uses a `camelCase` convention for prop names. For example, you'll write `tabIndex` instead of `tabindex`. You can convert existing HTML to JSX with an [online converter.](https://transform.tools/html-to-jsx)
</Note>
---
### Custom HTML elements {/*custom-html-elements*/}
If you render a tag with a dash, like `<my-element>`, React will assume you want to render a [custom HTML element.](https://developer.mozilla.org/en-US/docs/Web/Web_Components/Using_custom_elements) In React, rendering custom elements works differently from rendering built-in browser tags:
- All custom element props are serialized to strings and are always set using attributes.
- Custom elements accept `class` rather than `className`, and `for` rather than `htmlFor`.
If you render a built-in browser HTML element with an [`is`](https://developer.mozilla.org/en-US/docs/Web/HTML/Global_attributes/is) attribute, it will also be treated as a custom element.
<Note>
[A future version of React will include more comprehensive support for custom elements.](https://github.com/facebook/react/issues/11347#issuecomment-1122275286)
You can try it by upgrading React packages to the most recent experimental version:
- `react@experimental`
- `react-dom@experimental`
Experimental versions of React may contain bugs. Don't use them in production.
</Note>
---
## All SVG components {/*all-svg-components*/}
React supports all built-in browser SVG components. This includes:
* [`<a>`](https://developer.mozilla.org/en-US/docs/Web/SVG/Element/a)
* [`<animate>`](https://developer.mozilla.org/en-US/docs/Web/SVG/Element/animate)
* [`<animateMotion>`](https://developer.mozilla.org/en-US/docs/Web/SVG/Element/animateMotion)
* [`<animateTransform>`](https://developer.mozilla.org/en-US/docs/Web/SVG/Element/animateTransform)
* [`<circle>`](https://developer.mozilla.org/en-US/docs/Web/SVG/Element/circle)
* [`<clipPath>`](https://developer.mozilla.org/en-US/docs/Web/SVG/Element/clipPath)
* [`<defs>`](https://developer.mozilla.org/en-US/docs/Web/SVG/Element/defs)
* [`<desc>`](https://developer.mozilla.org/en-US/docs/Web/SVG/Element/desc)
* [`<discard>`](https://developer.mozilla.org/en-US/docs/Web/SVG/Element/discard)
* [`<ellipse>`](https://developer.mozilla.org/en-US/docs/Web/SVG/Element/ellipse)
* [`<feBlend>`](https://developer.mozilla.org/en-US/docs/Web/SVG/Element/feBlend)
* [`<feColorMatrix>`](https://developer.mozilla.org/en-US/docs/Web/SVG/Element/feColorMatrix)
* [`<feComponentTransfer>`](https://developer.mozilla.org/en-US/docs/Web/SVG/Element/feComponentTransfer)
* [`<feComposite>`](https://developer.mozilla.org/en-US/docs/Web/SVG/Element/feComposite)
* [`<feConvolveMatrix>`](https://developer.mozilla.org/en-US/docs/Web/SVG/Element/feConvolveMatrix)
* [`<feDiffuseLighting>`](https://developer.mozilla.org/en-US/docs/Web/SVG/Element/feDiffuseLighting)
* [`<feDisplacementMap>`](https://developer.mozilla.org/en-US/docs/Web/SVG/Element/feDisplacementMap)
* [`<feDistantLight>`](https://developer.mozilla.org/en-US/docs/Web/SVG/Element/feDistantLight)
* [`<feDropShadow>`](https://developer.mozilla.org/en-US/docs/Web/SVG/Element/feDropShadow)
* [`<feFlood>`](https://developer.mozilla.org/en-US/docs/Web/SVG/Element/feFlood)
* [`<feFuncA>`](https://developer.mozilla.org/en-US/docs/Web/SVG/Element/feFuncA)
* [`<feFuncB>`](https://developer.mozilla.org/en-US/docs/Web/SVG/Element/feFuncB)
* [`<feFuncG>`](https://developer.mozilla.org/en-US/docs/Web/SVG/Element/feFuncG)
* [`<feFuncR>`](https://developer.mozilla.org/en-US/docs/Web/SVG/Element/feFuncR)
* [`<feGaussianBlur>`](https://developer.mozilla.org/en-US/docs/Web/SVG/Element/feGaussianBlur)
* [`<feImage>`](https://developer.mozilla.org/en-US/docs/Web/SVG/Element/feImage)
* [`<feMerge>`](https://developer.mozilla.org/en-US/docs/Web/SVG/Element/feMerge)
* [`<feMergeNode>`](https://developer.mozilla.org/en-US/docs/Web/SVG/Element/feMergeNode)
* [`<feMorphology>`](https://developer.mozilla.org/en-US/docs/Web/SVG/Element/feMorphology)
* [`<feOffset>`](https://developer.mozilla.org/en-US/docs/Web/SVG/Element/feOffset)
* [`<fePointLight>`](https://developer.mozilla.org/en-US/docs/Web/SVG/Element/fePointLight)
* [`<feSpecularLighting>`](https://developer.mozilla.org/en-US/docs/Web/SVG/Element/feSpecularLighting)
* [`<feSpotLight>`](https://developer.mozilla.org/en-US/docs/Web/SVG/Element/feSpotLight)
* [`<feTile>`](https://developer.mozilla.org/en-US/docs/Web/SVG/Element/feTile)
* [`<feTurbulence>`](https://developer.mozilla.org/en-US/docs/Web/SVG/Element/feTurbulence)
* [`<filter>`](https://developer.mozilla.org/en-US/docs/Web/SVG/Element/filter)
* [`<foreignObject>`](https://developer.mozilla.org/en-US/docs/Web/SVG/Element/foreignObject)
* [`<g>`](https://developer.mozilla.org/en-US/docs/Web/SVG/Element/g)
* `<hatch>`
* `<hatchpath>`
* [`<image>`](https://developer.mozilla.org/en-US/docs/Web/SVG/Element/image)
* [`<line>`](https://developer.mozilla.org/en-US/docs/Web/SVG/Element/line)
* [`<linearGradient>`](https://developer.mozilla.org/en-US/docs/Web/SVG/Element/linearGradient)
* [`<marker>`](https://developer.mozilla.org/en-US/docs/Web/SVG/Element/marker)
* [`<mask>`](https://developer.mozilla.org/en-US/docs/Web/SVG/Element/mask)
* [`<metadata>`](https://developer.mozilla.org/en-US/docs/Web/SVG/Element/metadata)
* [`<mpath>`](https://developer.mozilla.org/en-US/docs/Web/SVG/Element/mpath)
* [`<path>`](https://developer.mozilla.org/en-US/docs/Web/SVG/Element/path)
* [`<pattern>`](https://developer.mozilla.org/en-US/docs/Web/SVG/Element/pattern)
* [`<polygon>`](https://developer.mozilla.org/en-US/docs/Web/SVG/Element/polygon)
* [`<polyline>`](https://developer.mozilla.org/en-US/docs/Web/SVG/Element/polyline)
* [`<radialGradient>`](https://developer.mozilla.org/en-US/docs/Web/SVG/Element/radialGradient)
* [`<rect>`](https://developer.mozilla.org/en-US/docs/Web/SVG/Element/rect)
* [`<script>`](https://developer.mozilla.org/en-US/docs/Web/SVG/Element/script)
* [`<set>`](https://developer.mozilla.org/en-US/docs/Web/SVG/Element/set)
* [`<stop>`](https://developer.mozilla.org/en-US/docs/Web/SVG/Element/stop)
* [`<style>`](https://developer.mozilla.org/en-US/docs/Web/SVG/Element/style)
* [`<svg>`](https://developer.mozilla.org/en-US/docs/Web/SVG/Element/svg)
* [`<switch>`](https://developer.mozilla.org/en-US/docs/Web/SVG/Element/switch)
* [`<symbol>`](https://developer.mozilla.org/en-US/docs/Web/SVG/Element/symbol)
* [`<text>`](https://developer.mozilla.org/en-US/docs/Web/SVG/Element/text)
* [`<textPath>`](https://developer.mozilla.org/en-US/docs/Web/SVG/Element/textPath)
* [`<title>`](https://developer.mozilla.org/en-US/docs/Web/SVG/Element/title)
* [`<tspan>`](https://developer.mozilla.org/en-US/docs/Web/SVG/Element/tspan)
* [`<use>`](https://developer.mozilla.org/en-US/docs/Web/SVG/Element/use)
* [`<view>`](https://developer.mozilla.org/en-US/docs/Web/SVG/Element/view)
<Note>
Similar to the [DOM standard,](https://developer.mozilla.org/en-US/docs/Web/API/Document_Object_Model) React uses a `camelCase` convention for prop names. For example, you'll write `tabIndex` instead of `tabindex`. You can convert existing SVG to JSX with an [online converter.](https://transform.tools/)
Namespaced attributes also have to be written without the colon:
* `xlink:actuate` becomes `xlinkActuate`.
* `xlink:arcrole` becomes `xlinkArcrole`.
* `xlink:href` becomes `xlinkHref`.
* `xlink:role` becomes `xlinkRole`.
* `xlink:show` becomes `xlinkShow`.
* `xlink:title` becomes `xlinkTitle`.
* `xlink:type` becomes `xlinkType`.
* `xml:base` becomes `xmlBase`.
* `xml:lang` becomes `xmlLang`.
* `xml:space` becomes `xmlSpace`.
* `xmlns:xlink` becomes `xmlnsXlink`.
</Note>

595
beta/src/content/apis/react-dom/components/input.md

@ -0,0 +1,595 @@
---
title: "<input>"
---
<Intro>
The [built-in browser `<input>` component](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/input) lets you render different kinds of form inputs.
```js
<input />
```
</Intro>
<InlineToc />
---
## Usage {/*usage*/}
### Displaying inputs of different types {/*displaying-inputs-of-different-types*/}
To display an input, render an `<input>` component. By default, it will be a text input. You can pass `type="checkbox"` for a checkbox, `type="radio"` for a radio button, [or one of the other input types.](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/input#input_types)
<Sandpack>
```js
export default function MyForm() {
return (
<>
<label>
Text input: <input name="myInput" />
</label>
<hr />
<label>
Checkbox: <input type="checkbox" name="myCheckbox" />
</label>
<hr />
<p>
Radio buttons:
<label>
<input type="radio" name="myRadio" value="option1" />
Option 1
</label>
<label>
<input type="radio" name="myRadio" value="option2" />
Option 2
</label>
<label>
<input type="radio" name="myRadio" value="option3" />
Option 3
</label>
</p>
</>
);
}
```
```css
label { display: block; }
input { margin: 5px; }
```
</Sandpack>
---
### Providing a label for an input {/*providing-a-label-for-an-input*/}
Typically, you will place every `<input>` inside a [`<label>`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/label) tag. This tells the browser that this label is associated with that input. When the user clicks the label, the browser will automatically focus the input. It's also essential for accessibility: a screen reader will announce the label caption when the user focuses the associated input.
If you can't nest `<input>` into a `<label>`, associate them by passing the same ID to `<input id>` and [`<label htmlFor>`.](https://developer.mozilla.org/en-US/docs/Web/API/HTMLLabelElement/htmlFor) To avoid conflicts between multiple instances of one component, generate such an ID with [`useId`.](/apis/react/useId)
<Sandpack>
```js
import { useId } from 'react';
export default function Form() {
const ageInputId = useId();
return (
<>
<label>
Your first name:
<input name="firstName" />
</label>
<hr />
<label htmlFor={ageInputId}>Your age:</label>
<input id={ageInputId} name="age" type="number" />
</>
);
}
```
```css
input { margin: 5px; }
```
</Sandpack>
---
### Providing an initial value for an input {/*providing-an-initial-value-for-an-input*/}
You can optionally specify the initial value for any input. Pass it as the `defaultValue` string for text inputs. Checkboxes and radio buttons should specify the initial value with the `defaultChecked` boolean instead.
<Sandpack>
```js
export default function MyForm() {
return (
<>
<label>
Text input: <input name="myInput" defaultValue="Some initial value" />
</label>
<hr />
<label>
Checkbox: <input type="checkbox" name="myCheckbox" defaultChecked={true} />
</label>
<hr />
<p>
Radio buttons:
<label>
<input type="radio" name="myRadio" value="option1" />
Option 1
</label>
<label>
<input
type="radio"
name="myRadio"
value="option2"
defaultChecked={true}
/>
Option 2
</label>
<label>
<input type="radio" name="myRadio" value="option3" />
Option 3
</label>
</p>
</>
);
}
```
```css
label { display: block; }
input { margin: 5px; }
```
</Sandpack>
---
### Reading the input values when submitting a form {/*reading-the-input-values-when-submitting-a-form*/}
Add a [`<form>`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/form) around your inputs with a [`<button type="submit">`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/button) inside. It will call your `<form onSubmit>` event handler. By default, the browser will send the form data to the current URL and refresh the page. You can override that behavior by calling `e.preventDefault()`. To read the form data, use [`new FormData(e.target)`](https://developer.mozilla.org/en-US/docs/Web/API/FormData).
<Sandpack>
```js
export default function MyForm() {
function handleSubmit(e) {
// Prevent the browser from reloading the page
e.preventDefault();
// Read the form data
const form = e.target;
const formData = new FormData(form);
// You can pass formData as a fetch body directly:
fetch('/some-api', { method: form.method, body: formData });
// Or you can work with it as a plain object:
const formJson = Object.fromEntries(formData.entries());
console.log(formJson);
}
return (
<form method="post" onSubmit={handleSubmit}>
<label>
Text input: <input name="myInput" defaultValue="Some initial value" />
</label>
<hr />
<label>
Checkbox: <input type="checkbox" name="myCheckbox" defaultChecked={true} />
</label>
<hr />
<p>
Radio buttons:
<label><input type="radio" name="myRadio" value="option1" /> Option 1</label>
<label><input type="radio" name="myRadio" value="option2" defaultChecked={true} /> Option 2</label>
<label><input type="radio" name="myRadio" value="option3" /> Option 3</label>
</p>
<hr />
<button type="reset">Reset form</button>
<button type="submit">Submit form</button>
</form>
);
}
```
```css
label { display: block; }
input { margin: 5px; }
```
</Sandpack>
<Note>
Give a `name` to every `<input>`, for example `<input name="firstName" defaultValue="Taylor" />`. The `name` you specified will be used as a key in the form data, for example `{ firstName: "Taylor" }`.
</Note>
<Pitfall>
By default, *any* `<button>` inside a `<form>` will submit it. This can be surprising! If you have your own custom `Button` React component, consider returning [`<button type="button">`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/input/button) instead of `<button>`. Then, to be explicit, use `<button type="submit">` for buttons that *are* supposed to submit the form.
</Pitfall>
---
### Controlling an input with a state variable {/*controlling-an-input-with-a-state-variable*/}
An input like `<input />` is *uncontrolled.* Even if you [pass an initial value](#providing-an-initial-value-for-an-input) like `<input defaultValue="Initial text" />`, your JSX only specifies the initial value. It does not control what the value should be right now.
**To render a _controlled_ input, pass the `value` prop to it (or `checked` for checkboxes and radios).** React will force the input to always have the `value` you passed. Typically, you will control an input by declaring a [state variable:](/apis/react/useState)
```js {2,6,7}
function Form() {
const [firstName, setFirstName] = useState(''); // Declare a state variable...
// ...
return (
<input
value={firstName} // ...force the input's value to match the state variable...
onChange={e => setFirstName(e.target.value)} // ... and update the state variable on any edits!
/>
);
}
```
A controlled input makes sense if you needed state anyway--for example, to re-render your UI on every edit:
```js {2,9}
function Form() {
const [firstName, setFirstName] = useState('');
return (
<>
<label>
First name:
<input value={firstName} onChange={e => setFirstName(e.target.value)} />
</label>
{firstName !== '' && <p>Your name is {firstName}.</p>}
...
```
It's also useful if you want to offer multiple ways to adjust the input state (for example, by clicking a button):
```js {3-4,10-11,14}
function Form() {
// ...
const [age, setAge] = useState('');
const ageAsNumber = Number(age);
return (
<>
<label>
Age:
<input
value={age}
onChange={e => setAge(e.target.value)}
type="number"
/>
<button onClick={() => setAge(ageAsNumber + 10)}>
Add 10 years
</button>
```
The `value` you pass to controlled components should not be `undefined` or `null`. If you need the initial value to be empty (such as with the `firstName` field below), initialize your state variable to an empty string (`''`).
<Sandpack>
```js
import { useState } from 'react';
export default function Form() {
const [firstName, setFirstName] = useState('');
const [age, setAge] = useState('20');
const ageAsNumber = Number(age);
return (
<>
<label>
First name:
<input
value={firstName}
onChange={e => setFirstName(e.target.value)}
/>
</label>
<label>
Age:
<input
value={age}
onChange={e => setAge(e.target.value)}
type="number"
/>
<button onClick={() => setAge(ageAsNumber + 10)}>
Add 10 years
</button>
</label>
{firstName !== '' &&
<p>Your name is {firstName}.</p>
}
{ageAsNumber > 0 &&
<p>Your age is {ageAsNumber}.</p>
}
</>
);
}
```
```css
label { display: block; }
input { margin: 5px; }
p { font-weight: bold; }
```
</Sandpack>
<Pitfall>
**If you pass `value` without `onChange`, it will be impossible to type into the input.** When you control an input by passing some `value` to it, you *force* it to always have the value you passed. So if you pass a state variable as a `value` but forget to update that state variable synchronously during the `onChange` event handler, React will revert the input after every keystroke back to the `value` that you specified.
</Pitfall>
---
### Optimizing re-rendering on every keystroke {/*optimizing-re-rendering-on-every-keystroke*/}
When you use a controlled input, you set the state on every keystroke. If the component containing your state re-renders a large tree, this can get slow. There's a few ways you can optimize re-rendering performance.
For example, suppose you start with a form that re-renders all page content on every keystroke:
```js {5-8}
function App() {
const [firstName, setFirstName] = useState('');
return (
<>
<form>
<input value={firstName} onChange={e => setFirstName(e.target.value)} />
</form>
<PageContent />
</>
);
}
```
Since `<PageContent />` doesn't rely on the input state, you can move the input state into its own component:
```js {4,10-17}
function App() {
return (
<>
<SignupForm />
<PageContent />
</>
);
}
function SignupForm() {
const [firstName, setFirstName] = useState('');
return (
<form>
<input value={firstName} onChange={e => setFirstName(e.target.value)} />
</form>
);
}
```
This significantly improves performance because now only `SignupForm` re-renders on every keystroke.
If there is no way to avoid re-rendering (for example, if `PageContent` depends on the search input's value), [`useDeferredValue`](/apis/react/useDeferredValue#deferring-re-rendering-for-a-part-of-the-ui) lets you keep the controlled input responsive even in the middle of a large re-render.
---
## Reference {/*reference*/}
### `<input>` {/*input*/}
To display an input, render the [built-in browser `<input>`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/input) component.
```js
<input name="myInput" />
```
[See more examples above.](#usage)
#### Props {/*props*/}
`<input>` supports all [common element props.](/apis/react-dom/components/common#props)
You can [make an input controlled](#controlling-an-input-with-a-state-variable) by passing one of these props:
* [`checked`](https://developer.mozilla.org/en-US/docs/Web/API/HTMLInputElement#checked): A boolean. For a checkbox input or a radio button, controls whether it is selected.
* [`value`](https://developer.mozilla.org/en-US/docs/Web/API/HTMLInputElement#value): A string. For a text input, controls its text. (For a radio button, specifies its form data.)
When you pass either of them, you must also pass an `onChange` handler that updates the passed value.
These `<input>` props are only relevant for uncontrolled inputs:
* [`defaultChecked`](https://developer.mozilla.org/en-US/docs/Web/API/HTMLInputElement#defaultChecked): A boolean. Specifies [the initial value](#providing-an-initial-value-for-an-input) for `type="checkbox"` and `type="radio"` inputs.
* [`defaultValue`](https://developer.mozilla.org/en-US/docs/Web/API/HTMLInputElement#defaultValue): A string. Specifies [the initial value](#providing-an-initial-value-for-an-input) for a text input.
These `<input>` props are relevant both for uncontrolled and controlled inputs:
* [`accept`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/input#accept): A string. Specifies which filetypes are accepted by a `type="file"` input.
* [`alt`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/input#alt): A string. Specifies the alternative image text for a `type="image"` input.
* [`capture`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/input#capture): A string. Specifies the media (microphone, video, or camera) captured by a `type="file"` input.
* [`autoComplete`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/input#autocomplete): A string. Specifies one of the possible [autocomplete behaviors.](https://developer.mozilla.org/en-US/docs/Web/HTML/Attributes/autocomplete#values)
* [`autoFocus`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/input#autofocus): A boolean. If `true`, React will focus the element on mount.
* [`dirname`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/input#dirname): A string. Specifies the form field name for the element's directionality.
* [`disabled`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/input#disabled): A boolean. If `true`, the input will not be interactive and will appear dimmed.
* `children`: `<input>` does not accept children.
* [`form`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/input#form): A string. Specifies the `id` of the `<form>` this input belongs to. If omitted, it's the closest parent form.
* [`formAction`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/input#formaction): A string. Overrides the parent `<form action>` for `type="submit"` and `type="image"`.
* [`formEnctype`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/input#formenctype): A string. Overrides the parent `<form enctype>` for `type="submit"` and `type="image"`.
* [`formMethod`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/input#formmethod): A string. Overrides the parent `<form method>` for `type="submit"` and `type="image"`.
* [`formNoValidate`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/input#formnovalidate): A string. Overrides the parent `<form noValidate>` for `type="submit"` and `type="image"`.
* [`formTarget`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/input#formtarget): A string. Overrides the parent `<form target>` for `type="submit"` and `type="image"`.
* [`height`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/input#height): A string. Specifies the image height for `type="image"`.
* [`list`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/input#list): A string. Specifies the `id` of the `<datalist>` with the autocomplete options.
* [`max`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/input#max): A number. Specifies the maximum value of numerical and datetime inputs.
* [`maxLength`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/input#maxlength): A number. Specifies the maximum length of text and other inputs.
* [`min`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/input#min): A number. Specifies the minimum value of numerical and datetime inputs.
* [`minLength`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/input#minlength): A number. Specifies the minimum length of text and other inputs.
* [`multiple`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/input#multiple): A boolean. Specifies whether multiple values are allowed for `<type="file"` and `type="email"`.
* [`name`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/input#name): A string. Specifies the name for this input that's [submitted with the form.](#reading-the-input-values-when-submitting-a-form)
* `onChange`: An [`Event` handler](/apis/react-dom/components/common#event-handler) function. Required for [controlled inputs.](#controlling-an-input-with-a-state-variable) Fires immediately when the input's value is changed by the user (for example, it fires on every keystroke). Behaves like the browser [`input` event.](https://developer.mozilla.org/en-US/docs/Web/API/HTMLElement/input_event)
* `onChangeCapture`: A version of `onChange` that fires in the [capture phase.](/learn/responding-to-events#capture-phase-events)
* [`onInput`](https://developer.mozilla.org/en-US/docs/Web/API/HTMLElement/input_event): An [`Event` handler](/apis/react-dom/components/common#event-handler) function. Fires immediately when the value is changed by the user. For historical reasons, in React it is idiomatic to use `onChange` instead which works similarly.
* `onInputCapture`: A version of `onInput` that fires in the [capture phase.](/learn/responding-to-events#capture-phase-events)
* [`onInvalid`](https://developer.mozilla.org/en-US/docs/Web/API/HTMLInputElement/invalid_event): An [`Event` handler](/apis/react-dom/components/common#event-handler) function. Fires if an input fails validation on form submit. Unlike the built-in `invalid` event, the React `onInvalid` event bubbles.
* `onInvalidCapture`: A version of `onInvalid` that fires in the [capture phase.](/learn/responding-to-events#capture-phase-events)
* [`onSelect`](https://developer.mozilla.org/en-US/docs/Web/API/HTMLInputElement/select_event): An [`Event` handler](/apis/react-dom/components/common#event-handler) function. Fires after the selection inside the `<input>` changes. React extends the `onSelect` event to also fire for empty selection and on edits (which may affect the selection).
* `onSelectCapture`: A version of `onSelect` that fires in the [capture phase.](/learn/responding-to-events#capture-phase-events)
* [`pattern`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/input#pattern): A string. Specifies the pattern that the `value` must match.
* [`placeholder`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/input#placeholder): A string. Displayed in a dimmed color when the input value is empty.
* [`readOnly`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/input#readonly): A boolean. If `true`, the input is not editable by the user.
* [`required`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/input#required): A boolean. If `true`, the value must be provided for the form to submit.
* [`size`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/input#size): A number. Similar to setting width, but the unit depends on the control.
* [`src`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/input#src): A string. Specifies the image source for a `type="image"` input.
* [`step`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/input#step): A positive number or an `'any'` string. Specifies the distance between valid values.
* [`type`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/input#type): A string. One of the [input types.](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/input#input_types)
* [`width`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/input#width): A string. Specifies the image width for a `type="image"` input.
#### Caveats {/*caveats*/}
- Checkboxes need `checked` (or `defaultChecked`), not `value` (or `defaultValue`).
- If a text input receives a string `value` prop, it will be [treated as controlled.](#controlling-an-input-with-a-state-variable)
- If a checkbox or a radio button receives a boolean `checked` prop, it will be [treated as controlled.](#controlling-an-input-with-a-state-variable)
- An input can't be both controlled and uncontrolled at the same time.
- An input cannot switch between being controlled or uncontrolled over its lifetime.
- Every controlled input needs an `onChange` event handler that synchronously updates its backing value.
---
## Troubleshooting {/*troubleshooting*/}
### My text input doesn't update when I type into it {/*my-text-input-doesnt-update-when-i-type-into-it*/}
If you render an input with `value` but no `onChange`, you will see an error in the console:
```js
// 🔴 Bug: controlled text input with no onChange handler
<input value={something} />
```
<ConsoleBlock level="error">
You provided a `value` prop to a form field without an `onChange` handler. This will render a read-only field. If the field should be mutable use `defaultValue`. Otherwise, set either `onChange` or `readOnly`.
</ConsoleBlock>
As the error message suggests, if you only wanted to [specify the *initial* value,](#providing-an-initial-value-for-an-input) pass `defaultValue` instead:
```js
// ✅ Good: uncontrolled input with an initial value
<input defaultValue={something} />
```
If you want [to control this input with a state variable,](#controlling-an-input-with-a-state-variable) specify an `onChange` handler:
```js
// ✅ Good: controlled input with onChange
<input value={something} onChange={e => setSomething(e.target.value)} />
```
If the value is intentionally read-only, add a `readOnly` prop to suppress the error:
```js
// ✅ Good: readonly controlled input without on change
<input value={something} readOnly={true} />
```
---
### My checkbox doesn't update when I click on it {/*my-checkbox-doesnt-update-when-i-click-on-it*/}
If you render a checkbox with `checked` but no `onChange`, you will see an error in the console:
```js
// 🔴 Bug: controlled checkbox with no onChange handler
<input type="checkbox" checked={something} />
```
<ConsoleBlock level="error">
You provided a `checked` prop to a form field without an `onChange` handler. This will render a read-only field. If the field should be mutable use `defaultChecked`. Otherwise, set either `onChange` or `readOnly`.
</ConsoleBlock>
As the error message suggests, if you only wanted to [specify the *initial* value,](#providing-an-initial-value-for-an-input) pass `defaultChecked` instead:
```js
// ✅ Good: uncontrolled checkbox with an initial value
<input type="checkbox" defaultChecked={something} />
```
If you want [to control this checkbox with a state variable,](#controlling-an-input-with-a-state-variable) specify an `onChange` handler:
```js
// ✅ Good: controlled checkbox with onChange
<input type="checkbox" checked={something} onChange={e => setSomething(e.target.checked)} />
```
<Pitfall>
You need to read `e.target.checked` rather than `e.target.value` for checkboxes.
</Pitfall>
If the checkbox is intentionally read-only, add a `readOnly` prop to suppress the error:
```js
// ✅ Good: readonly controlled input without on change
<input type="checkbox" checked={something} readOnly={true} />
```
---
### My input caret jumps to the beginning on every keystroke {/*my-input-caret-jumps-to-the-beginning-on-every-keystroke*/}
If you [control an input,](#controlling-an-input-with-a-state-variable) you must update its state variable to the input's value from the DOM during `onChange`.
You can't update it to something other than `e.target.value` (or `e.target.checked` for checkboxes):
```js
function handleChange(e) {
// 🔴 Bug: updating an input to something other than e.target.value
setFirstName(e.target.value.toUpperCase());
}
```
You also can't update it asynchronously:
```js
function handleChange(e) {
// 🔴 Bug: updating an input asynchronously
setTimeout(() => {
setFirstName(e.target.value);
}, 100);
}
```
To fix your code, update it synchronously to `e.target.value`:
```js
function handleChange(e) {
// ✅ Updating a controlled input to e.target.value synchronously
setFirstName(e.target.value);
}
```
If this doesn't fix the problem, it's possible that the input gets removed and re-added from the DOM on every keystroke. This can happen if you're accidentally [resetting state](/learn/preserving-and-resetting-state) on every re-render. For example, this can happen if the input or one of its parents always receives a different `key` attribute, or if you nest component definitions (which is not allowed in React and causes the "inner" component to always be considered a different tree).
---
### I'm getting an error: "A component is changing an uncontrolled input to be controlled" {/*im-getting-an-error-a-component-is-changing-an-uncontrolled-input-to-be-controlled*/}
If you provide a `value` to the component, it must remain a string throughout its lifetime.
You cannot pass `value={undefined}` first and later pass `value="some string"` because React won't know whether you want the component to be uncontrolled or controlled. A controlled component should always receive a string `value`, not `null` or `undefined`.
If your `value` is coming from an API or a state variable, it might be initialized to `null` or `undefined`. In that case, either set it to an empty string (`''`) initially, or pass `value={someValue ?? ''}` to ensure `value` is a string.
Similarly, if you pass `checked` to a checkbox, ensure it's always a boolean.

80
beta/src/content/apis/react-dom/components/option.md

@ -0,0 +1,80 @@
---
title: "<option>"
---
<Intro>
The [built-in browser `<option>` component](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/option) lets you render an option inside a [`<select>`](/apis/react-dom/components/select) box.
```js
<select>
<option value="someOption">Some option</option>
<option value="otherOption">Other option</option>
</select>
```
</Intro>
<InlineToc />
---
## Usage {/*usage*/}
### Displaying a select box with options {/*displaying-a-select-box-with-options*/}
Render a `<select>` with a list of `<option>` components inside to display a select box. Give each `<option>` a `value` representing the data to be submitted with the form.
[Read more about displaying a `<select>` with a list of `<option>` components.](/apis/react-dom/components/select)
<Sandpack>
```js
export default function FruitPicker() {
return (
<label>
Pick a fruit:
<select name="selectedFruit">
<option value="apple">Apple</option>
<option value="banana">Banana</option>
<option value="orange">Orange</option>
</select>
</label>
);
}
```
```css
select { margin: 5px; }
```
</Sandpack>
---
## Reference {/*reference*/}
### `<option>` {/*option*/}
The [built-in browser `<option>` component](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/select) lets you render an option inside a [`<select>`](/apis/react-dom/components/select) box.
```js
<select>
<option value="someOption">Some option</option>
<option value="otherOption">Other option</option>
</select>
```
#### Props {/*props*/}
`<option>` supports all [common element props.](/apis/react-dom/components/common#props)
Additionally, `<option>` supports these props:
* [`disabled`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/option#disabled): A boolean. If `true`, the option will not be selectable and will appear dimmed.
* [`label`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/option#label): A string. Specifies the meaning of the option. If not specified, the text inside the option is used.
* [`value`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/option#value): The value to be used [when submitting the parent `<select>` in a form](/apis/react-dom/components/select#reading-the-select-box-value-when-submitting-a-form) if this option is selected.
#### Caveats {/*caveats*/}
* React does not support the `selected` attribute on `<option>`. Instead, pass this option's `value` to the parent [`<select defaultValue>`](/apis/react-dom/components/select#providing-an-initially-selected-option) for an uncontrolled select box, or [`<select value>`](/apis/react-dom/components/select#controlling-a-select-box-with-a-state-variable) for a controlled select box.

70
beta/src/content/apis/react-dom/components/progress.md

@ -0,0 +1,70 @@
---
title: "<progress>"
---
<Intro>
The [built-in browser `<progress>` component](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/progress) lets you render a progress indicator.
```js
<progress value={0.5} />
```
</Intro>
<InlineToc />
---
## Usage {/*usage*/}
### Controlling a progress indicator {/*controlling-a-progress-indicator*/}
To display a progress indicator, render a `<progress>` component. You can pass a number `value` between `0` and the `max` value you specify. If you don't pass a `max` value, it will assumed to be `1` by default.
If the operation is not ongoing, pass `value={null}` to put the progress indicator into an indeterminate state.
<Sandpack>
```js
export default function App() {
return (
<>
<progress value={0} />
<progress value={0.5} />
<progress value={0.7} />
<progress value={75} max={100} />
<progress value={1} />
<progress value={null} />
</>
);
}
```
```css
progress { display: block; }
```
</Sandpack>
---
## Reference {/*reference*/}
### `<progress>` {/*progress*/}
To display a progress indicator, render the [built-in browser `<progress>`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/progress) component.
```js
<progress value={0.5} />
```
#### Props {/*props*/}
`<progress>` supports all [common element props.](/apis/react-dom/components/common#props)
Additionally, `<progress>` supports these props:
* [`max`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/progress#attr-max): A number. Specifies the maximum `value`. Defaults to `1`.
* [`value`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/progress#attr-value): A number between `0` and `max`, or `null` for intermedinate progress. Specifies how much was done.

385
beta/src/content/apis/react-dom/components/select.md

@ -0,0 +1,385 @@
---
title: "<select>"
---
<Intro>
The [built-in browser `<select>` component](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/select) lets you render a select box with options.
```js
<select>
<option value="someOption">Some option</option>
<option value="otherOption">Other option</option>
</select>
```
</Intro>
<InlineToc />
---
## Usage {/*usage*/}
### Displaying a select box with options {/*displaying-a-select-box-with-options*/}
Render a `<select>` with a list of `<option>` components inside to display a select box. Give each `<option>` a `value` representing the data to be submitted with the form.
<Sandpack>
```js
export default function FruitPicker() {
return (
<label>
Pick a fruit:
<select name="selectedFruit">
<option value="apple">Apple</option>
<option value="banana">Banana</option>
<option value="orange">Orange</option>
</select>
</label>
);
}
```
```css
select { margin: 5px; }
```
</Sandpack>
---
### Providing a label for a select box {/*providing-a-label-for-a-select-box*/}
Typically, you will place every `<select>` inside a [`<label>`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/label) tag. This tells the browser that this label is associated with that select box. When the user clicks the label, the browser will automatically focus the select box. It's also essential for accessibility: a screen reader will announce the label caption when the user focuses the select box.
If you can't nest `<select>` into a `<label>`, associate them by passing the same ID to `<select id>` and [`<label htmlFor>`.](https://developer.mozilla.org/en-US/docs/Web/API/HTMLLabelElement/htmlFor) To avoid conflicts between multiple instances of one component, generate such an ID with [`useId`.](/apis/react/useId)
<Sandpack>
```js
import { useId } from 'react';
export default function Form() {
const vegetableSelectId = useId();
return (
<>
<label>
Pick a fruit:
<select name="selectedFruit">
<option value="apple">Apple</option>
<option value="banana">Banana</option>
<option value="orange">Orange</option>
</select>
</label>
<hr />
<label htmlFor={vegetableSelectId}>
Pick a vegetable:
</label>
<select id={vegetableSelectId} name="selectedVegetable">
<option value="cucumber">Cucumber</option>
<option value="corn">Corn</option>
<option value="tomato">Tomato</option>
</select>
</>
);
}
```
```css
select { margin: 5px; }
```
</Sandpack>
---
### Providing an initially selected option {/*providing-an-initially-selected-option*/}
By default, the browser will select the first `<option>` in the list. To select a different option by default, pass that `<option>`'s `value` as the `defaultValue` to the `<select>` element.
<Sandpack>
```js
export default function FruitPicker() {
return (
<label>
Pick a fruit:
<select name="selectedFruit" defaultValue="orange">
<option value="apple">Apple</option>
<option value="banana">Banana</option>
<option value="orange">Orange</option>
</select>
</label>
);
}
```
```css
select { margin: 5px; }
```
</Sandpack>
<Pitfall>
Unlike in HTML, passing a `selected` attribute to an individual `<option>` is not supported.
</Pitfall>
---
### Enabling multiple selection {/*enabling-multiple-selection*/}
Pass `multiple={true}` to the `<select>` to let the user select multiple options. In that case, if you also specify `defaultValue` to choose the initially selected options, it must be an array.
<Sandpack>
```js
export default function FruitPicker() {
return (
<label>
Pick some fruits:
<select
name="selectedFruit"
defaultValue={['orange', 'banana']}
multiple={true}
>
<option value="apple">Apple</option>
<option value="banana">Banana</option>
<option value="orange">Orange</option>
</select>
</label>
);
}
```
```css
select { display: block; margin-top: 10px; width: 200px; }
```
</Sandpack>
---
### Reading the select box value when submitting a form {/*reading-the-select-box-value-when-submitting-a-form*/}
Add a [`<form>`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/form) around your textarea with a [`<button type="submit">`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/button) inside. It will call your `<form onSubmit>` event handler. By default, the browser will send the form data to the current URL and refresh the page. You can override that behavior by calling `e.preventDefault()`. To read the form data, use [`new FormData(e.target)`](https://developer.mozilla.org/en-US/docs/Web/API/FormData).
<Sandpack>
```js
export default function EditPost() {
function handleSubmit(e) {
// Prevent the browser from reloading the page
e.preventDefault();
// Read the form data
const form = e.target;
const formData = new FormData(form);
// You can pass formData as a fetch body directly:
fetch('/some-api', { method: form.method, body: formData });
// You can generate a URL out of it, as the browser does by default:
console.log(new URLSearchParams(formData).toString());
// You can work with it as a plain object.
const formJson = Object.fromEntries(formData.entries());
console.log(formJson); // (!) This doesn't include multiple select values
// Or you can get an array of name-value pairs.
console.log([...formData.entries()]);
}
return (
<form method="post" onSubmit={handleSubmit}>
<label>
Pick your favorite fruit:
<select name="selectedFruit" defaultValue="orange">
<option value="apple">Apple</option>
<option value="banana">Banana</option>
<option value="orange">Orange</option>
</select>
</label>
<label>
Pick all your favorite vegetables:
<select
name="selectedVegetables"
multiple={true}
defaultValue={['corn', 'tomato']}
>
<option value="cucumber">Cucumber</option>
<option value="corn">Corn</option>
<option value="tomato">Tomato</option>
</select>
</label>
<hr />
<button type="reset">Reset</button>
<button type="submit">Submit</button>
</form>
);
}
```
```css
label, select { display: block; }
label { margin-bottom: 20px; }
```
</Sandpack>
<Note>
Give a `name` to your `<select>`, for example `<select name="selectedFruit" />`. The `name` you specified will be used as a key in the form data, for example `{ selectedFruit: "orange" }`.
If you use `<select multiple={true}>`, the [`FormData`](https://developer.mozilla.org/en-US/docs/Web/API/FormData) you'll read from the form will include each selected value as a separate name-value pair. Look closely at the console logs in the example above.
</Note>
<Pitfall>
By default, *any* `<button>` inside a `<form>` will submit it. This can be surprising! If you have your own custom `Button` React component, consider returning [`<button type="button">`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/input/button) instead of `<button>`. Then, to be explicit, use `<button type="submit">` for buttons that *are* supposed to submit the form.
</Pitfall>
---
### Controlling a select box with a state variable {/*controlling-a-select-box-with-a-state-variable*/}
A select box like `<select />` is *uncontrolled.* Even if you [pass an initially selected value](#providing-an-initially-selected-option) like `<select defaultValue="orange" />`, your JSX only specifies the initial value, not the value right now.
**To render a _controlled_ select box, pass the `value` prop to it.** React will force the select box to always have the `value` you passed. Typically, you will control a select box by declaring a [state variable:](/apis/react/useState)
```js {2,6,7}
function FruitPicker() {
const [selectedFruit, setSelectedFruit] = useState('orange'); // Declare a state variable...
// ...
return (
<select
value={selectedFruit} // ...force the select's value to match the state variable...
onChange={e => setSelectedFruit(e.target.value)} // ... and update the state variable on any change!
>
<option value="apple">Apple</option>
<option value="banana">Banana</option>
<option value="orange">Orange</option>
</select>
);
}
```
This is useful if you want to re-render some part of the UI in response to every selection.
<Sandpack>
```js
import { useState } from 'react';
export default function FruitPicker() {
const [selectedFruit, setSelectedFruit] = useState('orange');
const [selectedVegs, setSelectedVegs] = useState(['corn', 'tomato']);
return (
<>
<label>
Pick a fruit:
<select
value={selectedFruit}
onChange={e => setSelectedFruit(e.target.value)}
>
<option value="apple">Apple</option>
<option value="banana">Banana</option>
<option value="orange">Orange</option>
</select>
</label>
<hr />
<label>
Pick all your favorite vegetables:
<select
multiple={true}
value={selectedVegs}
onChange={e => {
const options = [...e.target.selectedOptions];
const values = options.map(option => option.value);
setSelectedVegs(values);
}}
>
<option value="cucumber">Cucumber</option>
<option value="corn">Corn</option>
<option value="tomato">Tomato</option>
</select>
</label>
<hr />
<p>Your favorite fruit: {selectedFruit}</p>
<p>Your favorite vegetables: {selectedVegs.join(', ')}</p>
</>
);
}
```
```css
select { margin-bottom: 10px; display: block; }
```
</Sandpack>
<Pitfall>
**If you pass `value` without `onChange`, it will be impossible to select an option.** When you control a select box by passing some `value` to it, you *force* it to always have the value you passed. So if you pass a state variable as a `value` but forget to update that state variable synchronously during the `onChange` event handler, React will revert the select box after every keystroke back to the `value` that you specified.
Unlike in HTML, passing a `selected` attribute to an individual `<option>` is not supported.
</Pitfall>
<hr />
## Reference {/*reference*/}
### `<select>` {/*select*/}
To display a select box, render the [built-in browser `<select>`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/select) component.
```js
<select>
<option value="someOption">Some option</option>
<option value="otherOption">Other option</option>
</select>
```
[See more examples above.](#usage)
#### Props {/*props*/}
`<select>` supports all [common element props.](/apis/react-dom/components/common#props)
You can [make a select box controlled](#controlling-a-select-box-with-a-state-variable) by passing a `value` prop:
* `value`: A string (or an array of strings for [`multiple={true}`](#enabling-multiple-selection)). Controls which option is selected. Every value string match the `value` of some `<option>` nested inside the `<select>`.
When you pass `value`, you must also pass an `onChange` handler that updates the passed value.
If your `<select>` is uncontrolled, you may pass the `defaultValue` prop instead:
* `defaultValue`: A string (or an array of strings for [`multiple={true}`](#enabling-multiple-selection)). Specifies [the initially selected option.](#providing-an-initially-selected-option)
These `<select>` props are relevant both for uncontrolled and controlled select boxs:
* [`autoComplete`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/select#attr-autocomplete): A string. Specifies one of the possible [autocomplete behaviors.](https://developer.mozilla.org/en-US/docs/Web/HTML/Attributes/autocomplete#values)
* [`autoFocus`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/select#attr-autofocus): A boolean. If `true`, React will focus the element on mount.
* `children`: `<select>` accepts [`<option>`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/option), [`<optgroup>`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/optgroup), and [`<datalist>`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/optgroup) components as children. You can also pass your own components as long as they eventually render one of the allowed components. If you pass your own components that eventually render `<option>` tags, each `<option>` you render must have a `value`.
* [`disabled`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/select#attr-disabled): A boolean. If `true`, the select box will not be interactive and will appear dimmed.
* [`form`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/select#attr-form): A string. Specifies the `id` of the `<form>` this select box belongs to. If omitted, it's the closest parent form.
* [`multiple`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/select#attr-multiple): A boolean. If `true`, the browser allows [multiple selection.](#enabling-multiple-selection)
* [`name`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/select#attr-name): A string. Specifies the name for this select box that's [submitted with the form.](#reading-the-select-box-value-when-submitting-a-form)
* `onChange`: An [`Event` handler](/apis/react-dom/components/common#event-handler) function. Required for [controlled select boxes.](#controlling-a-select-box-with-a-state-variable) Fires immediately when the user picks a different option. Behaves like the browser [`input` event.](https://developer.mozilla.org/en-US/docs/Web/API/HTMLElement/input_event)
* `onChangeCapture`: A version of `onChange` that fires in the [capture phase.](/learn/responding-to-events#capture-phase-events)
* [`onInput`](https://developer.mozilla.org/en-US/docs/Web/API/HTMLElement/input_event): An [`Event` handler](/apis/react-dom/components/common#event-handler) function. Fires immediately when the value is changed by the user. For historical reasons, in React it is idiomatic to use `onChange` instead which works similarly.
* `onInputCapture`: A version of `onInput` that fires in the [capture phase.](/learn/responding-to-events#capture-phase-events)
* [`onInvalid`](https://developer.mozilla.org/en-US/docs/Web/API/HTMLInputElement/invalid_event): An [`Event` handler](/apis/react-dom/components/common#event-handler) function. Fires if an input fails validation on form submit. Unlike the built-in `invalid` event, the React `onInvalid` event bubbles.
* `onInvalidCapture`: A version of `onInvalid` that fires in the [capture phase.](/learn/responding-to-events#capture-phase-events)
* [`required`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/select#attr-required): A boolean. If `true`, the value must be provided for the form to submit.
* [`size`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/select#attr-size): A number. For `multiple={true}` selects, specifies the preferred number of initially visible items.
#### Caveats {/*caveats*/}
- Unlike in HTML, passing a `selected` attribute to `<option>` is not supported. Instead, use [`<select defaultValue>`](#providing-an-initially-selected-option) for uncontrolled select boxes and [`<select value>`](#controlling-a-select-box-with-a-state-variable) for controlled select boxes.
- If a select box receives a `value` prop, it will be [treated as controlled.](#controlling-a-select-box-with-a-state-variable)
- A select box can't be both controlled and uncontrolled at the same time.
- A select box cannot switch between being controlled or uncontrolled over its lifetime.
- Every controlled select box needs an `onChange` event handler that synchronously updates its backing value.

423
beta/src/content/apis/react-dom/components/textarea.md

@ -0,0 +1,423 @@
---
title: "<textarea>"
---
<Intro>
The [built-in browser `<textarea>` component](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/textarea) lets you render a multiline text input.
```js
<textarea />
```
</Intro>
<InlineToc />
---
## Usage {/*usage*/}
### Displaying a text area {/*displaying-a-text-area*/}
Render `<textarea>` to display a text area. You can specify its default size with the [`rows`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/textarea#rows) and [`cols`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/textarea#cols) attributes, but by default the user will be able to resize it. To disable resizing, you can specify `resize: none` in the CSS.
<Sandpack>
```js
export default function NewPost() {
return (
<label>
Write your post:
<textarea name="postContent" rows={4} cols={40} />
</label>
);
}
```
```css
input { margin-left: 5px; }
textarea { margin-top: 10px; }
label { margin: 10px; }
label, textarea { display: block; }
```
</Sandpack>
---
### Providing a label for a text area {/*providing-a-label-for-a-text-area*/}
Typically, you will place every `<textarea>` inside a [`<label>`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/label) tag. This tells the browser that this label is associated with that text area. When the user clicks the label, the browser will focus the text area. It's also essential for accessibility: a screen reader will announce the label caption when the user focuses the text area.
If you can't nest `<textarea>` into a `<label>`, associate them by passing the same ID to `<textarea id>` and [`<label htmlFor>`.](https://developer.mozilla.org/en-US/docs/Web/API/HTMLLabelElement/htmlFor) To avoid conflicts between instances of one component, generate such an ID with [`useId`.](/apis/react/useId)
<Sandpack>
```js
import { useId } from 'react';
export default function Form() {
const postTextAreaId = useId();
return (
<>
<label htmlFor={postTextAreaId}>
Write your post:
</label>
<textarea
id={postTextAreaId}
name="postContent"
rows={4}
cols={40}
/>
</>
);
}
```
```css
input { margin: 5px; }
```
</Sandpack>
---
### Providing an initial value for a text area {/*providing-an-initial-value-for-a-text-area*/}
You can optionally specify the initial value for the text area. Pass it as the `defaultValue` string.
<Sandpack>
```js
export default function EditPost() {
return (
<label>
Edit your post:
<textarea
name="postContent"
defaultValue="I really enjoyed biking yesterday!"
rows={4}
cols={40}
/>
</label>
);
}
```
```css
input { margin-left: 5px; }
textarea { margin-top: 10px; }
label { margin: 10px; }
label, textarea { display: block; }
```
</Sandpack>
<Pitfall>
Unlike in HTML, passing initial text like `<textarea>Some content</textarea>` is not supported.
</Pitfall>
---
### Reading the text area value when submitting a form {/*reading-the-text-area-value-when-submitting-a-form*/}
Add a [`<form>`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/form) around your textarea with a [`<button type="submit">`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/button) inside. It will call your `<form onSubmit>` event handler. By default, the browser will send the form data to the current URL and refresh the page. You can override that behavior by calling `e.preventDefault()`. To read the form data, use [`new FormData(e.target)`](https://developer.mozilla.org/en-US/docs/Web/API/FormData).
<Sandpack>
```js
export default function EditPost() {
function handleSubmit(e) {
// Prevent the browser from reloading the page
e.preventDefault();
// Read the form data
const form = e.target;
const formData = new FormData(form);
// You can pass formData as a fetch body directly:
fetch('/some-api', { method: form.method, body: formData });
// Or you can work with it as a plain object:
const formJson = Object.fromEntries(formData.entries());
console.log(formJson);
}
return (
<form method="post" onSubmit={handleSubmit}>
<label>
Post title: <input name="postTitle" defaultValue="Biking" />
</label>
<label>
Edit your post:
<textarea
name="postContent"
defaultValue="I really enjoyed biking yesterday!"
rows={4}
cols={40}
/>
</label>
<hr />
<button type="reset">Reset edits</button>
<button type="submit">Save post</button>
</form>
);
}
```
```css
label { display: block; }
input { margin: 5px; }
```
</Sandpack>
<Note>
Give a `name` to your `<textarea>`, for example `<textarea name="postContent" />`. The `name` you specified will be used as a key in the form data, for example `{ postContent: "Your post" }`.
</Note>
<Pitfall>
By default, *any* `<button>` inside a `<form>` will submit it. This can be surprising! If you have your own custom `Button` React component, consider returning [`<button type="button">`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/input/button) instead of `<button>`. Then, to be explicit, use `<button type="submit">` for buttons that *are* supposed to submit the form.
</Pitfall>
---
### Controlling a text area with a state variable {/*controlling-a-text-area-with-a-state-variable*/}
A text area like `<textarea />` is *uncontrolled.* Even if you [pass an initial value](#providing-an-initial-value-for-a-text-area) like `<textarea defaultValue="Initial text" />`, your JSX only specifies the initial value, not the value right now.
**To render a _controlled_ text area, pass the `value` prop to it.** React will force the text area to always have the `value` you passed. Typically, you will control a text area by declaring a [state variable:](/apis/react/useState)
```js {2,6,7}
function NewPost() {
const [postContent, setPostContent] = useState(''); // Declare a state variable...
// ...
return (
<textarea
value={postContent} // ...force the input's value to match the state variable...
onChange={e => setPostContent(e.target.value)} // ... and update the state variable on any edits!
/>
);
}
```
This is useful if you want to re-render some part of the UI in response to every keystroke.
<Sandpack>
```js
import { useState } from 'react';
import MarkdownPreview from './MarkdownPreview.js';
export default function MarkdownEditor() {
const [postContent, setPostContent] = useState('_Hello,_ **Markdown**!');
return (
<>
<label>
Enter some markdown:
<textarea
value={postContent}
onChange={e => setPostContent(e.target.value)}
/>
</label>
<hr />
<MarkdownPreview markdown={postContent} />
</>
);
}
```
```js MarkdownPreview.js
import { Remarkable } from 'remarkable';
const md = new Remarkable();
export default function MarkdownPreview({ markdown }) {
const renderedHTML = md.render(markdown);
return <div dangerouslySetInnerHTML={{__html: renderedHTML}} />;
}
```
```json package.json
{
"dependencies": {
"react": "latest",
"react-dom": "latest",
"react-scripts": "latest",
"remarkable": "2.0.1"
},
"scripts": {
"start": "react-scripts start",
"build": "react-scripts build",
"test": "react-scripts test --env=jsdom",
"eject": "react-scripts eject"
}
}
```
```css
textarea { display: block; margin-top: 5px; margin-bottom: 10px; }
```
</Sandpack>
<Pitfall>
**If you pass `value` without `onChange`, it will be impossible to type into the text area.** When you control an text area by passing some `value` to it, you *force* it to always have the value you passed. So if you pass a state variable as a `value` but forget to update that state variable synchronously during the `onChange` event handler, React will revert the text area after every keystroke back to the `value` that you specified.
</Pitfall>
---
## Reference {/*reference*/}
### `<textarea>` {/*textarea*/}
To display a text area, render the [built-in browser `<textarea>`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/textarea) component.
```js
<textarea name="postContent" />
```
[See more examples above.](#usage)
#### Props {/*props*/}
`<textarea>` supports all [common element props.](/apis/react-dom/components/common#props)
You can [make a text area controlled](#controlling-a-text-area-with-a-state-variable) by passing a `value` prop:
* `value`: A string. Controls the text inside the text area.
When you pass `value`, you must also pass an `onChange` handler that updates the passed value.
If your `<textarea>` is uncontrolled, you may pass the `defaultValue` prop instead:
* `defaultValue`: A string. Specifies [the initial value](#providing-an-initial-value-for-a-text-area) for a text area.
These `<textarea>` props are relevant both for uncontrolled and controlled text areas:
* [`autoComplete`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/textarea#attr-autocomplete): Either `'on'` or `'off'`. Specifies the autocomplete behavior.
* [`autoFocus`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/textarea#attr-autofocus): A boolean. If `true`, React will focus the element on mount.
* `children`: `<textarea>` does not accept children. To set the initial value, use `defaultValue`.
* [`cols`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/textarea#attr-cols): A number. Specifies the default width in average character widths. Defaults to `20`.
* [`disabled`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/textarea#attr-disabled): A boolean. If `true`, the input will not be interactive and will appear dimmed.
* [`form`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/textarea#attr-form): A string. Specifies the `id` of the `<form>` this input belongs to. If omitted, it's the closest parent form.
* [`maxLength`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/textarea#attr-maxlength): A number. Specifies the maximum length of text.
* [`minLength`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/textarea#attr-minlength): A number. Specifies the minimum length of text.
* [`name`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/input#name): A string. Specifies the name for this input that's [submitted with the form.](#reading-the-textarea-value-when-submitting-a-form)
* `onChange`: An [`Event` handler](/apis/react-dom/components/common#event-handler) function. Required for [controlled text areas.](#controlling-a-text-area-with-a-state-variable) Fires immediately when the input's value is changed by the user (for example, it fires on every keystroke). Behaves like the browser [`input` event.](https://developer.mozilla.org/en-US/docs/Web/API/HTMLElement/input_event)
* `onChangeCapture`: A version of `onChange` that fires in the [capture phase.](/learn/responding-to-events#capture-phase-events)
* [`onInput`](https://developer.mozilla.org/en-US/docs/Web/API/HTMLElement/input_event): An [`Event` handler](/apis/react-dom/components/common#event-handler) function. function. Fires immediately when the value is changed by the user. For historical reasons, in React it is idiomatic to use `onChange` instead which works similarly.
* `onInputCapture`: A version of `onInput` that fires in the [capture phase.](/learn/responding-to-events#capture-phase-events)
* [`onInvalid`](https://developer.mozilla.org/en-US/docs/Web/API/HTMLInputElement/invalid_event): An [`Event` handler](/apis/react-dom/components/common#event-handler) function. Fires if an input fails validation on form submit. Unlike the built-in `invalid` event, the React `onInvalid` event bubbles.
* `onInvalidCapture`: A version of `onInvalid` that fires in the [capture phase.](/learn/responding-to-events#capture-phase-events)
* [`onSelect`](https://developer.mozilla.org/en-US/docs/Web/API/HTMLTextAreaElement/select_event): An [`Event` handler](/apis/react-dom/components/common#event-handler) function. Fires after the selection inside the `<textarea>` changes. React extends the `onSelect` event to also fire for empty selection and on edits (which may affect the selection).
* `onSelectCapture`: A version of `onSelect` that fires in the [capture phase.](/learn/responding-to-events#capture-phase-events)
* [`placeholder`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/textarea#attr-placeholder): A string. Displayed in a dimmed color when the text area value is empty.
* [`readOnly`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/textarea#attr-readonly): A boolean. If `true`, the text area is not editable by the user.
* [`required`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/textarea#attr-required): A boolean. If `true`, the value must be provided for the form to submit.
* [`rows`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/textarea#attr-rows): A number. Specifies the default height in average character heights. Defaults to `2`.
* [`wrap`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/textarea#attr-wrap): Either `'hard'`, `'soft'`, or `'off'`. Specifies how the text should be wrapped when submitting a form.
#### Caveats {/*caveats*/}
- Passing children like `<textarea>something</textarea>` is not allowed. [Use `defaultValue` for initial content.](#providing-an-initial-value-for-a-text-area)
- If a text area receives a string `value` prop, it will be [treated as controlled.](#controlling-a-text-area-with-a-state-variable)
- A text area can't be both controlled and uncontrolled at the same time.
- A text area cannot switch between being controlled or uncontrolled over its lifetime.
- Every controlled text area needs an `onChange` event handler that synchronously updates its backing value.
---
## Troubleshooting {/*troubleshooting*/}
### My text area doesn't update when I type into it {/*my-text-area-doesnt-update-when-i-type-into-it*/}
If you render a text area with `value` but no `onChange`, you will see an error in the console:
```js
// 🔴 Bug: controlled text area with no onChange handler
<textarea value={something} />
```
<ConsoleBlock level="error">
You provided a `value` prop to a form field without an `onChange` handler. This will render a read-only field. If the field should be mutable use `defaultValue`. Otherwise, set either `onChange` or `readOnly`.
</ConsoleBlock>
As the error message suggests, if you only wanted to [specify the *initial* value,](#providing-an-initial-value-for-a-text-area) pass `defaultValue` instead:
```js
// ✅ Good: uncontrolled text area with an initial value
<textarea defaultValue={something} />
```
If you want [to control this text area with a state variable,](#controlling-a-text-area-with-a-state-variable) specify an `onChange` handler:
```js
// ✅ Good: controlled text area with onChange
<textarea value={something} onChange={e => setSomething(e.target.value)} />
```
If the value is intentionally read-only, add a `readOnly` prop to suppress the error:
```js
// ✅ Good: readonly controlled text area without on change
<textarea value={something} readOnly={true} />
```
---
### My text area caret jumps to the beginning on every keystroke {/*my-text-area-caret-jumps-to-the-beginning-on-every-keystroke*/}
If you [control a text area,](#controlling-a-text-area-with-a-state-variable) you must update its state variable to the text area's value from the DOM during `onChange`.
You can't update it to something other than `e.target.value`:
```js
function handleChange(e) {
// 🔴 Bug: updating an input to something other than e.target.value
setFirstName(e.target.value.toUpperCase());
}
```
You also can't update it asynchronously:
```js
function handleChange(e) {
// 🔴 Bug: updating an input asynchronously
setTimeout(() => {
setFirstName(e.target.value);
}, 100);
}
```
To fix your code, update it synchronously to `e.target.value`:
```js
function handleChange(e) {
// ✅ Updating a controlled input to e.target.value synchronously
setFirstName(e.target.value);
}
```
If this doesn't fix the problem, it's possible that the text area gets removed and re-added from the DOM on every keystroke. This can happen if you're accidentally [resetting state](/learn/preserving-and-resetting-state) on every re-render. For example, this can happen if the text area or one of its parents always receives a different `key` attribute, or if you nest component definitions (which is not allowed in React and causes the "inner" component to remount on every render).
---
### I'm getting an error: "A component is changing an uncontrolled input to be controlled" {/*im-getting-an-error-a-component-is-changing-an-uncontrolled-input-to-be-controlled*/}
If you provide a `value` to the component, it must remain a string throughout its lifetime.
You cannot pass `value={undefined}` first and later pass `value="some string"` because React won't know whether you want the component to be uncontrolled or controlled. A controlled component should always receive a string `value`, not `null` or `undefined`.
If your `value` is coming from an API or a state variable, it might be initialized to `null` or `undefined`. In that case, either set it to an empty string (`''`) initially, or pass `value={someValue ?? ''}` to ensure `value` is a string.

4
beta/src/content/learn/manipulating-the-dom-with-refs.md

@ -211,7 +211,7 @@ This is because **Hooks must only be called at the top-level of your component.*
One possible way around this is to get a single ref to their parent element, and then use DOM manipulation methods like [`querySelectorAll`](https://developer.mozilla.org/en-US/docs/Web/API/Document/querySelectorAll) to "find" the individual child nodes from it. However, this is brittle and can break if your DOM structure changes.
Another solution is to **pass a function to the `ref` attribute.** This is called a "ref callback". React will call your ref callback with the DOM node when it's time to set the ref, and with `null` when it's time to clear it. This lets you maintain your own array or a [Map](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Map), and access any ref by its index or some kind of ID.
Another solution is to **pass a function to the `ref` attribute.** This is called a [`ref` callback.](/apis/react-dom/components/common#ref-callback) React will call your ref callback with the DOM node when it's time to set the ref, and with `null` when it's time to clear it. This lets you maintain your own array or a [Map](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Map), and access any ref by its index or some kind of ID.
This example shows how you can use this approach to scroll to an arbitrary node in a long list:
@ -318,7 +318,7 @@ li {
</Sandpack>
In this example, `itemsRef` doesn't hold a single DOM node. Instead, it holds a [Map](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Map) from item ID to a DOM node. ([Refs can hold any values!](/learn/referencing-values-with-refs)) The `ref` callback on every list item takes care to update the Map:
In this example, `itemsRef` doesn't hold a single DOM node. Instead, it holds a [Map](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Map) from item ID to a DOM node. ([Refs can hold any values!](/learn/referencing-values-with-refs)) The [`ref` callback](/apis/react-dom/components/common#ref-callback) on every list item takes care to update the Map:
```js
<li

33
beta/src/sidebarAPIs.json

@ -122,7 +122,38 @@
]
},
{
"title": "react-dom",
"title": "react-dom: Components",
"path": "/apis/react-dom/components",
"hasSeparator": true,
"routes": [
{
"title": "Common (e.g. <div>)",
"path": "/apis/react-dom/components/common"
},
{
"title": "<input>",
"path": "/apis/react-dom/components/input"
},
{
"title": "<option>",
"path": "/apis/react-dom/components/option"
},
{
"title": "<progress>",
"path": "/apis/react-dom/components/progress"
},
{
"title": "<select>",
"path": "/apis/react-dom/components/select"
},
{
"title": "<textarea>",
"path": "/apis/react-dom/components/textarea"
}
]
},
{
"title": "react-dom: APIs",
"path": "/apis/react-dom",
"routes": [
{

Loading…
Cancel
Save