Provide a renderer-agnostic equivalent of setNativeProps()
See original GitHub issueDan asked me to open up an issue: https://twitter.com/dan_abramov/status/1246883821477339139
My proposal is to extend React with a small hook that allows us to mutate nodes without causing render. React has no official means to deal with fast occurring updates and libraries like react-spring and framer-motion already do something similar but in a way that forces them to carry a lot of burden.
import React, { useMutation }
function A() {
const [specialRef, set] = useMutation()
useEffect(() => {
// the following would execute sync and without causing render
// going through the same channel as a regular props update with all
// the internal interpolation (100 --> "100px")
set({ style: { left: 100 } })
}, [])
return <div ref={specialRef} ... />
It uses the fact that reconcilers know how to handle props, something we don’t know in userland unless we cause render to set fresh props, which is not at all optimal for animation or anything frame based. react-dom for instance knows what margin: 3px
is, react-three-fiber knows what position: [1,2,3]
is, and so on. These details are defined in the reconciler:
commitUpdate(instance: any, updatePayload: any, type: string, oldProps: any, newProps: any, fiber: Reconciler.Fiber)
If libraries could use this knowledge from outside they could deal with any platform. Animation libraries like react-spring or framer-motion would turn x-platform in one strike, they could animate everything: dom nodes, react native views, meshes, hardware diodes. We could finally write libraries that are not reliant on platforms.
Issue Analytics
- State:
- Created 3 years ago
- Reactions:55
- Comments:15 (9 by maintainers)
Let me try to rephrase your request to make sure I understand it.
I think you’re asking for a way for renderer-agnostic libraries to tell React to imperatively synchronously update a host node with given props. But without actually specifying how that update gets applied because presumably the renderer’s host config already knows that. So the host node itself is opaque.
setNativeProps was removed in Fabric because it had undefined behavior that couldn’t be modeled the same way between paper and fabric. Also, in paper all of the communication is async so this function could t happen sync. That could work in Fabric though.
The land mines with setNativeProps is that it was essentially setting state on the native views and there wasn’t a guarantee for when that would get reset since it can be out of sync with a React render.
For example: React renders a view with background blue SetNativeProps to set the background to green React update to change border color. Should background reset to blue?
React doesn’t know that the background is green, only the native view (or div) does. This makes it more complicated when that native view is actually removed from the hierarchy because of view flattening. That should be totally transparent to the user, but it can change the views that are rendered.
If something like this is added, it should have defined behavior for these kinds of gotchas.