Make `<textarea>` a void element
Description
Fixes #3296 by raising an error when trying to provide children to <textarea> and asserting the correct way to provide default value to it in the docs, which is the defaultvalue attribute also added with this PR.
Documents the peculiarities of <textarea> and the void elements in general.
Checklist
- [x] I have reviewed my own code
- [x] I have added tests
Visit the preview URL for this PR (updated for commit 66e8ad3):
https://yew-rs--pr3465-textarea2void-gtm0ku6i.web.app
(expires Mon, 30 Oct 2023 20:02:30 GMT)
🔥 via Firebase Hosting GitHub Action 🌎
Size Comparison
| examples | master (KB) | pull request (KB) | diff (KB) | diff (%) |
|---|---|---|---|---|
| async_clock | 102.908 | 103.111 | +0.203 | +0.197% |
| boids | 175.774 | 175.980 | +0.206 | +0.117% |
| communication_child_to_parent | 95.388 | 95.588 | +0.200 | +0.210% |
| communication_grandchild_with_grandparent | 109.124 | 109.401 | +0.277 | +0.254% |
| communication_grandparent_to_grandchild | 105.791 | 106.059 | +0.268 | +0.253% |
| communication_parent_to_child | 92.864 | 93.068 | +0.204 | +0.220% |
| contexts | 113.500 | 113.768 | +0.268 | +0.236% |
| counter | 89.268 | 89.476 | +0.208 | +0.233% |
| counter_functional | 90.005 | 90.206 | +0.201 | +0.224% |
| dyn_create_destroy_apps | 92.440 | 92.642 | +0.201 | +0.218% |
| file_upload | 103.600 | 103.801 | +0.201 | +0.194% |
| function_memory_game | 174.675 | 174.881 | +0.206 | +0.118% |
| function_router | 352.530 | 352.890 | +0.359 | +0.102% |
| function_todomvc | 163.555 | 163.764 | +0.209 | +0.128% |
| futures | 227.837 | 228.081 | +0.244 | +0.107% |
| game_of_life | 112.282 | 112.483 | +0.201 | +0.179% |
| immutable | 188.883 | 189.249 | +0.366 | +0.194% |
| inner_html | 86.047 | 86.249 | +0.202 | +0.235% |
| js_callback | 113.455 | 113.664 | +0.209 | +0.184% |
| keyed_list | 201.029 | 201.229 | +0.200 | +0.100% |
| mount_point | 89.269 | 89.478 | +0.209 | +0.234% |
| nested_list | 115.902 | 116.094 | +0.191 | +0.165% |
| node_refs | 96.365 | 96.566 | +0.201 | +0.209% |
| password_strength | 1752.378 | 1752.579 | +0.201 | +0.011% |
| portals | 98.466 | 98.733 | +0.268 | +0.272% |
| router | 318.460 | 318.819 | +0.359 | +0.113% |
| simple_ssr | 144.185 | 144.498 | +0.313 | +0.217% |
| ssr_router | 390.318 | 390.656 | +0.338 | +0.087% |
| suspense | 119.118 | 119.396 | +0.278 | +0.234% |
| timer | 91.816 | 92.019 | +0.202 | +0.220% |
| timer_functional | 100.520 | 100.722 | +0.202 | +0.201% |
| todomvc | 143.861 | 144.070 | +0.209 | +0.145% |
| two_apps | 89.977 | 90.178 | +0.201 | +0.224% |
| web_worker_fib | 139.025 | 139.294 | +0.269 | +0.193% |
| web_worker_prime | 190.481 | 190.877 | +0.396 | +0.208% |
| webgl | 88.572 | 88.772 | +0.200 | +0.226% |
✅ None of the examples has changed their size significantly.
Benchmark - SSR
Yew Master
| Benchmark | Round | Min (ms) | Max (ms) | Mean (ms) | Standard Deviation |
|---|---|---|---|---|---|
| Baseline | 10 | 356.259 | 360.214 | 358.342 | 1.220 |
| Hello World | 10 | 617.614 | 621.970 | 618.595 | 1.736 |
| Function Router | 10 | 2103.588 | 2110.469 | 2107.901 | 2.268 |
| Concurrent Task | 10 | 1007.181 | 1008.852 | 1008.116 | 0.506 |
| Many Providers | 10 | 1467.052 | 1497.431 | 1478.223 | 10.437 |
Pull Request
| Benchmark | Round | Min (ms) | Max (ms) | Mean (ms) | Standard Deviation |
|---|---|---|---|---|---|
| Baseline | 10 | 319.270 | 321.213 | 319.621 | 0.573 |
| Hello World | 10 | 625.760 | 630.120 | 627.441 | 1.611 |
| Function Router | 10 | 2110.309 | 2126.143 | 2117.153 | 5.067 |
| Concurrent Task | 10 | 1007.520 | 1008.821 | 1008.317 | 0.411 |
| Many Providers | 10 | 1437.229 | 1465.041 | 1446.262 | 8.209 |
Why not recommend setting value? ~defaultValue works because defaultValue is a property on HTMLTextareaElement. Using value is how you should be interacting with the text area anyway. There's no point of having a textarea that you can't read from (technically, you can, with node refs but that is not the best way of doing things)
We wouldn't recommend setting value because the MDN docs for <textarea> state explicitly that it doesn't work, and because children of <textarea> define not its value, but its default, initial value, which is exactly what setting ~defaultValue does as well.
The value attribute doesn't work on textarea but Yew has special handling for value for both input and textarea that makes it work (it makes value and ~value behave the same). If you want to listen to oninput on the text area and react to user input, you need to use the value property.
See this playground
But the paragraph I've added to "html/elements" docs is specifically about the peculiarity of <textarea>: normally it accepts children, which define its defaultValue, but in Yew it's a void element and instead of children, ~defaultValue is provided, though value should indeed also be documented, I'll add that right now.
Wait, why does <input>'s value need special handling if it already defines it?
Wait, why does
<input>'svalueneed special handling if it already defines it?
The special handling predates the ~property syntax and controlled elements need it to be set as a property
But then is it really special for <input>?
It's special because the value is always set as property, not attribute, for input
Does that make a difference in case of <input>? I'm just wondering if it's worth it to explain all that in the docs or just pretend that <input> is a perfectly normal element
Why not recommend setting value?
Setting a value makes an element controlled. An element with defaultvalue should remain uncontrolled.
But then is it really special for
<input>?
Special handling for value and checked are required as these properties are controlled. This means that values are restored to the one provided to <input /> on every render regardless of whether a value is changed. The value displayed in an input is always in sync with the state associated with the value.
For other attributes, it only updates when an attribute is changed, added or removed.
There's definitely something wrong with the benchmarking CI action