Git Product home page Git Product logo

Comments (9)

peterkogo avatar peterkogo commented on June 11, 2024

The code you are referring to is a utility for adding edges. If you don't want to pass the edges array, the useReactFlow hook also exports an addEdges utility.
Or am I misunderstanding something?

from xyflow.

psychedelicious avatar psychedelicious commented on June 11, 2024

I don't want to add an edge to an array of edges. I want to create an edge object that I can manipulate directly, without needing to extract it from an array or reactflow's internally managed state.

Something like this:

import type { Connection, Edge } from 'reactflow';
import { assert } from 'tsafe';

/**
 * Gets the edge id for a connection
 * Copied from: https://github.com/xyflow/xyflow/blob/v11/packages/core/src/utils/graph.ts#L44-L45
 * Requested for this to be exported in: https://github.com/xyflow/xyflow/issues/4290
 * @param connection The connection to get the id for
 * @returns The edge id
 */
const getEdgeId = (connection: Connection): string => {
  const { source, sourceHandle, target, targetHandle } = connection;
  return `reactflow__edge-${source}${sourceHandle || ''}-${target}${targetHandle || ''}`;
};

/**
 * Converts a connection to an edge
 * @param connection The connection to convert to an edge
 * @returns The edge
 * @throws If the connection is invalid (e.g. missing source, sourcehandle, target, or targetHandle)
 */
export const connectionToEdge = (connection: Connection): Edge => {
  const { source, sourceHandle, target, targetHandle } = connection;
  assert(source && sourceHandle && target && targetHandle, 'Invalid connection');
  return {
    source,
    sourceHandle,
    target,
    targetHandle,
    id: getEdgeId({ source, sourceHandle, target, targetHandle }),
  };
};

This isn't complicated to implement on my own, but I'd prefer to not be concerned with ID format or any other implementation details from reactflow.

from xyflow.

peterkogo avatar peterkogo commented on June 11, 2024

Is this just about the id? There is no id format that React Flow enforces other than it has to be a string and unique. If you want to generate IDs for real world projects, I suggest you simply use UUIDs. You can generate one using the window.crypto API of browsers.

from xyflow.

psychedelicious avatar psychedelicious commented on June 11, 2024

No, it's not just about the id. It's about creating an edge from a connection, with the guarantee that it is identical to the edge that would be created by reactflow, given the input edge params or connection object.

The same problem exists for nodes.

To state the problem in a different way: reactflow encourages users to provide their own state management and handle it on a fairly low level, but it is missing some basic utilities to support this. For example, directly creating an edge or node that I may immediately manipulate without needing to add them to state or an array. I have to review the internal implementation addEdge or addNode to be confident my edge and node are created correctly.

from xyflow.

bcakmakoglu avatar bcakmakoglu commented on June 11, 2024

directly creating an edge or node that I may immediately manipulate without needing to add them to state or an array.

What exactly is preventing you from doing this though? You can create an object, type it properly if you're using TypeScript and you're good, or what's missing that a helper would solve?

I have to review the internal implementation addEdge or addNode to be confident my edge and node are created correctly.

What do you mean by "created correctly" exactly?
As long as you fulfill the requirements of the respective element types (nodes need an id and a position, edges need an id, source and target node id) they would be "created correctly".
Maybe there's a misconception that adding a node or edge would somehow create a new object with properties on it that you didn't explicitly pass?
Besides the required (mostly internal) properties, ReactFlow won't add stuff so if you pass an edge like this

const newEdge: Edge = {
	id: 'e1->2',
	source: '1',
	target: '2',
}

It will (mostly) just stay that, there won't be anything else on it.

There are some errors that can happen though, which you can listen to with the onError prop you can use to listen for these (by default they will be printed as a console warning, but only in dev).
For example if you try to add an edge without a source or target node id..

from xyflow.

psychedelicious avatar psychedelicious commented on June 11, 2024

Of course nothing is stopping me, and I have been doing that since I started using reactflow some time ago. I shared a small utility in this issue that does this for edges.

I don't mind if this request goes nowhere. But in an effort to clarify the the request...

Besides the required (mostly internal) properties

Yeah, these are the properties I don't want to be responsible for.

It will (mostly) just stay that

Again, I don't want to be responsible for whatever "mostly" doesn't include.

I have a data format that is an abstraction of the reactflow state. I need to translate between this enriched data format and reactflow nodes and edges regularly. Sometimes, when creating a node or edge, I need to manipulate it in some way before adding it to the application state.

The key thing here is that reactflow may or may not have internal implementation details that dictate the shape of edges and nodes. As a library user, I shouldn't need to know about these details, implement them, or keep track of changing upstream types.

For edges, reactflow provides two helpers:

  • Creating the edge object and immediately adding it to an array.
  • Creating the edge object and adding it to the internally-managed reactflow state.

In both of these cases, if I want the edge object (with whatever additional data reactflow may or may not add to it), I need to extract it from that array or state.

I'm asking for a third helper:

  • Create the edge object without adding it to an array or the internal state - just return it.

Finally, I understand the ID format doesn't affect any functionality, but it's rather nice to use a consistent format everywhere, no? Sometimes, I can rely on reactflow's internal handling to add an edge, but other times I need to create it myself. I want these two actions to result in the same state, given the same edge/connection params.

from xyflow.

bcakmakoglu avatar bcakmakoglu commented on June 11, 2024

Yeah, these are the properties I don't want to be responsible for.

Where does the assumption come from that you are responsible for these values? 😄
You don't have to (and shouldn't) pass these values at all.
Is the problem that you don't want to have these properties when translating from one state to another? Otherwise I'm still not quite sure what the issue is.

I need to manipulate it in some way before adding it to the application state.

Again, what is stopping you from doing so? You said yourself there's nothing preventing you from doing this, no?
Is the feature request a function (as you posted above) that throws when you use an invalid element definition?
Or what exactly is this function supposed to do except literally just return the same object you pass into it?

The key thing here is that reactflow may or may not have internal implementation details that dictate the shape of edges and nodes.

Feels like another assumption that there is some shape that you don't know about even though the base requirements are laid out already and you can use TypeScript to properly type the elements so you'd get feedback whether the shape is acceptable or not.
Anything that doesn't belong on a Node or Edge object needs to go into it's data property - that is what it's for. Any additional info etc. you need belongs into that data object.

I am still not quite sure what this feature request is supposed to solve exactly, it still feels very vague to me even with the explanation above as it seems like there are some assumptions being made about how ReactFlow works and handles your nodes/edges.

Maybe it would help if you could showcase a specific example where this helper would be used, why it would fill a gap that currently exists, how these cases wouldn't work as well without the helpers etc. - that might make it more obvious what exactly you are looking for since I might just be slow to understand 😄

from xyflow.

peterkogo avatar peterkogo commented on June 11, 2024

React Flow is a declarative flow graph renderer. You input nodes & edges with a specific format and it renders it for you. There is no logic attached to ids because we don't want to dictate how people manage their data ids. The same thing applies to state management. We don't want to trap anyone in any specific state or data management pattern, which in a way is what declarative systems tend to provide.

The key thing here is that reactflow may or may not have internal implementation details that dictate the shape of edges and nodes. As a library user, I shouldn't need to know about these details, implement them, or keep track of changing upstream types.

The only thing an edge needs to have is a unique id, so it can be identified, and a specific source and target handle. I don't think an edge can be defined by less information and that is also the only thing you have to provide. We don't know what edges you want to connect, you have to concern yourself with these details as a library user. There are no upstream changes to the types, the edges have and will almost certainly be always defined by these information.

from xyflow.

psychedelicious avatar psychedelicious commented on June 11, 2024

Ok, thanks for the continued discussion and reassurance. I won't worry about upstream changes, will create and use helpers as are suited to my application, and will rely on TS to alert me if anything does change. Thanks for your work on reactflow.

from xyflow.

Related Issues (20)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.