#Stale state in `onConnectEnd` after updating in `onConnect`

1 messages · Page 1 of 1 (latest)

neon crow
#

Hello! I have an app using React Flow with some state that includes nodes & edges, like this:

const [nodes, setNodes] = useNodesState<NodeData>([]);
const [edges, setEdges] = useEdgesState<EdgeData>([]);

I then have both onConnect and onConnectEnd callbacks defined. In both callbacks, I want to edit the edges, something like this:

const onConnect = useCallback((connection: Connection) => {
    // onConnect can add a new edge
    const newEdges = deepCopy(edges);
    newEdges.push({/* new edge data */});
    setEdges(newEdges);
}, [edges]);

const onConnectEnd = useCallback(() => {
    // onConnectEnd unchecks some flags on existing edges
    const newEdges = deepCopy(edges);
    for (const edge of newEdges) {
        edge.flag = false;
    }
    setEdges(newEdges);
}, [edges]);

HOWEVER, I noticed that onConnectEnd will never see the edges set by onConnect, so it will basically "undo" the added edge because it will reset the edges to the previous stale state. I assume this is because both callbacks are invoked by the same caller, so they are bound to the same state "snapshot" of state - onConnectEnd doesn't get a chance to be updated and pick up the new state before it is called. Is there anything I can do about this?

cloud sinew
#

Why dont you do this onConnectEnd logic inside onConnect? If you really want to have this flag logic inside onConnectEnd then you can set the recent edges in onConnect to a ref and then use that ref inside onConnectEnd to get the updated edges

neon crow
#

I do it inside onConnectEnd because there is a corresponding update in onConnectStart that I wanna undo. I guess this is expected behavior and I have to work around it? IMO this feel buggy from a user perspective, though I can see how it's tricky to fix... at least some warning in documentation

cloud sinew
#

Its not buggy. This is how react works. You can try the ref method I suggested if you want to use the onConnectEnd logic

neon crow
#

I understand why it works this way, but don't you think it's misleading to give users 2 callbacks without warning them that they are called without a re-render, and what the consequences are? It's good to have clarity on this though, I will do the ref workaround. Thanks.