[MAJOR]
Deprecatedcomponent.base
[MAJOR]
RemovereplaceNode
, use this technique instead)[MAJOR]
Removed select<option>
fix for IE11, using select in IE11 will always require you to specify avalue
attribute[MAJOR]
Removed automatic suffixing ofpx
to dimensional style attributes[MAJOR]
Forward ref by default on functional components (this is not the case for compat)[MINOR]
Add truely controlled components[MINOR]
AddcreateRoot
API[MAJOR]
Changeoptions._hook
to get an internal passed in (devtools)
PR's that weren't backported yet, do they work?
- Verify with sandbox #3210
- I don't know how to test this yet #3260
- Verify in browser #3226
- #3280 Not merged yet need some input
- #3222 Same as above
- Make this work #3306
- #3696
- Investigate if the return value of
createRoot()
can be re-used as a root Node... - Add specific tests for root nodes
- initial mount with same/different parentDOM as parent
- mounting on rerender with same/different parentDOM as parent
- diffing with same/different parentDOM as parent (inert portal node & normal portal node)
- diffing and switching between same <-> different
- toggling siblings to root nodes with same/different parentDOM
- Ensure interesting sibling/children patterns
- text children and text siblings
- dom children and dom siblings
- null children and null siblings
- multiple Fragment children & multiple Fragment siblings
- Check out portals.test.js for inspiration
-
Address many TODOs
-
Move refs to internal renderCallbacks
-
Consider converting Fragment (and other special nodes, e.g. root, Portal, context?) to be numbers instead of functions with special diff handling
One benefit of using numbers for Roots/Portals is that a portal could be created with a
null
_parentDOM prop and still be marked as a root type. Particularly, this is useful for Suspense and would remove the need for the call togetParentDom
inSuspense.render
With the above suggestion, remember to update getParentDom, getDomSibling, etc. to handle a
null
_parentDom
-
Consider simply rerendering all Suspense children when one of its Promises resolves. Might simplify the suspense tracking by avoiding the need to track pendingSuspensionCount and suspenders list.
With the approach above, consider maybe syncing unsuspending on the "nextFrame" to gather all Promises that resolved in this microtask/frame and rerendering them in one pass
- Reduce allocations for text nodes
- Investigate skip-index tracking instead of while loop
- Loop multiple times - recursive diff, unmount children, place child
- Combine placeChild and unmounting loop?? Do placeChild backwards? Do unmounting first then placeChild loop
- Explore replacing children in
internal._children
as we diff instead of building up a new array each time
-
Logic to begin (re)rendering an internal is sorta scattered around (top level render/hydrate, rerenderComponent, diffChildren), particularly the logic to resume suspended hydration. Could we consolidate this logic into a single function?
Perhaps reuse this function in the new extensible Component API?
-
Could
addCommitCallback()
use the samepush()===1
technique as the commit queue to enqueue the given Internal incommitCallback
?if (internal._commitCallbacks.push(callback) === 1) commitQueue.push(internal);
-
Controlled components could be implemented by keeping a WeakMap of DOM to Internal, rather than hanging underscore properties off of DOM nodes.
-
Decide if we actually want to support silent reparenting via
_parentDom
during patch. We don't reparent without destroying+recreating a tree anywhere else, and createPortal likely should support that in the first place. Plus, supporting this is likely a few bytes that could be removed if not explicitly necessary. -
Add a ref queue, and re-enable the global shared refs tests when the queue orders all unmounts before all mounts.
-
TYPE_FUNCTION
could instead beTYPE_COMPONENT
, right now its duplicative ofTYPE_CLASS
- One possible implementation for effect queues: Internal nodes can have a local queue of effects for that node while a global queue contains the internal nodes that have effects.
- Feature: Top-level render handles Fragment root
- Golf everything! Look for @TODO(golf)
- Look for ways to optimize DOM element diffing, specifically how we diff props
- Investigate diffing props before or after children
- Investigate inlining the loops in diffProps to capture special props (dangerouslySetInnerHTML, value, checked, multiple)
- Revisit all replaceNode tests
- Top-level
render()
no longer accepts areplaceNode
argument, and does not removed unmatched DOM nodes
- Top-level
- Use a special VNode (e.g. Root node) that reparents all children into a new DOM node (like Portals). Currently suspense manually does this but I think it is buggy in that it doesn't properly reset all dom pointers we currently maintain (implemented in #3053)
- Need a way to trigger updates on VNodes that may need mounting or patching. I'm thinking backing nodes will help here so when a node suspends, we can maintain its suspended state on the backing node and not the component which may need to be nulled or remounted (i.e. constructor & lifecycles called again) (re: the bug about calling forceUpdate on a suspended hydration component)
- Maintain the state (i.e. whether or not a node's last render suspended) as a flag on the VNode. This flag would be useful for commit or unmount option hooks to discover that that a suspended node has successfully rerendered or unmounted. Once that is detected the nearest Suspense node that is waiting can be updated as such (no more overriding render or componentWillUnmount!)