Document the design decisions
This commit is contained in:
@@ -49,6 +49,11 @@ function MiniMapNodes({
|
|||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
{nodes.map((nodeId) => (
|
{nodes.map((nodeId) => (
|
||||||
|
// The split of responsibilities between MiniMapNodes and
|
||||||
|
// NodeComponentWrapper may appear weird. However, it’s designed to
|
||||||
|
// minimize the cost of updates when individual nodes change.
|
||||||
|
//
|
||||||
|
// For more details, see a similar commit in `NodeRenderer/index.tsx`.
|
||||||
<NodeComponentWrapper
|
<NodeComponentWrapper
|
||||||
key={nodeId}
|
key={nodeId}
|
||||||
id={nodeId}
|
id={nodeId}
|
||||||
|
|||||||
@@ -77,6 +77,29 @@ const NodeRenderer = (props: NodeRendererProps) => {
|
|||||||
<div className="react-flow__nodes" style={containerStyle}>
|
<div className="react-flow__nodes" style={containerStyle}>
|
||||||
{nodeIds.map((nodeId) => {
|
{nodeIds.map((nodeId) => {
|
||||||
return (
|
return (
|
||||||
|
// The split of responsibilities between NodeRenderer and
|
||||||
|
// NodeComponentWrapper may appear weird. However, it’s designed to
|
||||||
|
// minimize the cost of updates when individual nodes change.
|
||||||
|
//
|
||||||
|
// For example, when you’re dragging a single node, that node gets
|
||||||
|
// updated multiple times per second. If `NodeRenderer` were to update
|
||||||
|
// every time, it would have to re-run the `nodes.map()` loop every
|
||||||
|
// time. This gets pricey with hundreds of nodes, especially if every
|
||||||
|
// loop cycle does more than just rendering a JSX element!
|
||||||
|
//
|
||||||
|
// As a result of this choice, we took the following implementation
|
||||||
|
// decisions:
|
||||||
|
// - NodeRenderer subscribes *only* to node IDs – and therefore
|
||||||
|
// rerender *only* when visible nodes are added or removed.
|
||||||
|
// - NodeRenderer performs all operations the result of which can be
|
||||||
|
// shared between nodes (such as creating the `ResizeObserver`
|
||||||
|
// instance, or subscribing to `selector`). This means extra prop
|
||||||
|
// drilling into `NodeComponentWrapper`, but it means we need to run
|
||||||
|
// these operations only once – instead of once per node.
|
||||||
|
// - Any operations that you’d normally write inside `nodes.map` are
|
||||||
|
// moved into `NodeComponentWrapper`. This ensures they are
|
||||||
|
// memorized – so if `NodeRenderer` *has* to rerender, it only
|
||||||
|
// needs to regenerate the list of nodes, nothing else.
|
||||||
<NodeComponentWrapper
|
<NodeComponentWrapper
|
||||||
key={nodeId}
|
key={nodeId}
|
||||||
id={nodeId}
|
id={nodeId}
|
||||||
|
|||||||
Reference in New Issue
Block a user