Recently I was browsing some React libraries I need to work on. My criteria for selection was to find new and not so many famous ones but they should also be useful for scalable projects. I hunted various categories from app state management to real-time web sockets. While those were useful and were used by thousands of developers, there was this one which was someone hidden under some big names.
This is React Flow, and as described in their repo:
React Flow is a library for building node-based graphs. You can easily implement custom node types and it comes with components like a mini-map and graph controls.
I chose this because I think it's useful to make interactive graphs uniquely and yes, it's quite easy to get started! So, let's make something, let's make a cool node-based graph with React Flow. π
Well, first some features π
Here are the top features or reasons why you should use React Flow library in your React app:
Easy to integrate and work on: It wouldn't take you more than 5 mins to see your first graph live in the app. That's what I call 'easy'!
Comes with extra plugins: You want a minimap just like you see in Sublime Text or you may want to add controls to your graph with panning/zooming? Say no more. The support is great and can be done with less code.
Customizable: The entire library can be worked on multiple nodes, interactivities, and styles.
Let's start! π¨βπ»
1. Installation:
Just grab your old friend NPM and run the following command (of course after you're done creating a React app):
npm install react-flow-renderer
Make sure it's installed correctly by going to your package.json file and looking for react-flow-renderer
as a dependency.
2. Creating our first graph:
We need to clear out a few terms first. Here are some:
Elements: It's an object which is like a container of all the 'nodes' and the 'edges'.
Nodes: These are the individual boxes which may contain some text or information.
Edges: This is like a connector between two nodes. If you want the graph to show a connection between two or more nodes, you create edges. These can be characterised by the presence of a
source
and atarget
attribute.Node types: There are three of them available. The first, 'input πͺ' which can also be the source node. Second is the 'default π§' similar to the default node you get and the third one is the 'output π©' that can be used to show the result of a process. As we know the library is highly customisable so we can create our node type as a 'custom π¨' one.
Edge types: Similar to node types you get a 'straight', 'default' and a 'step' type. You can even go ahead and have a custom edge type!
Graph control plugin: A very handy plugin to add features like zoom-in, zoom-out and focus on the graph.
- Mini map plugin: If you have a complex or a large graph, this will show you a map of the entire diagram on a small box from where you get the overview.
Okay, enough, I'll use these terms from now on.
To make a new graph we need to add elements, some styling and render them. First, make the elements
object containing the necessary data for your nodes.
const elements = [
{ id: "1", data: { label: "Parent" }, position: { x: 500, y: 150 } },
{ id: "2", data: { label: "First child" }, position: { x: 400, y: 250 } },
{ id: "e1-2", source: "1", target: "2", animated: true }
];
We make 2 nodes here with unique id
value, some label
s and default positions with respective x
and y
coordinate values. The third object is the edge that connected the source
node with id
1 to target
node. Also, for that fancy dotted animation, we set the boolean value to true
.
Next, we need to add basic styles to our nodes. This is required to render or else, you'll be greeted with the following error:
"The React Flow parent container needs a width and a height to render the graph."
Something you don't want to mess with (which I did because I thought styles aren't necessary! Meh...)
const graphStyles = { width: "100%", height: "500px" };
We simply provide what it said in the error. A default value of width
and height
.
Next, we make the BasicGraph
function which needs elements
and style
attributes inside the <ReactFlow />
component.
const BasicGraph = () => <ReactFlow elements={elements} style={graphStyles} />;
Let's render it by passing the component inside our return
:
export default function App() {
return <BasicGraph />;
}
3. Create a custom node:
For this, we make a new element object called customElement
but this time, let's add styles inside this one because we need a custom style
, data
and the starting position
.
const customElement = [
{
id: "1",
style: {
background: "#454052",
width: 200,
color: "#fff",
fontSize: "20px",
fontFamily: "Helvetica",
boxShadow: "5px 5px 5px 0px rgba(0,0,0,.10)"
},
data: { label: "My custom node" },
position: { x: 500, y: 250 }
},
{
id: "2",
style: {
background: "#fff",
width: 400,
color: "#454052",
fontSize: "25px",
fontFamily: "Helvetica",
boxShadow: "5px 5px 5px 0px rgba(0,0,0,.10)"
},
data: { label: "My second custom node π" },
position: { x: 550, y: 300 }
}
];
See how we have different id
values, use custom style
just like the CSS-in-JS concept and have a label
. Most of this is self-explanatory as this is really simple to use and implement.
4. Experiment with edge styles:
Let's hop on to edges! Here, we change the elements
object we made earlier for nodes as per our requirement. Here, I've made quite a complex one:
const elements = [
{
id: "1",
type: "input",
data: { label: "Master Node" },
position: { x: 50, y: 50 }
},
{ id: "2", data: { label: "Node 2" }, position: { x: 100, y: 100 } },
{ id: "3", data: { label: "Node 3" }, position: { x: 250, y: 150 } },
{ id: "4", data: { label: "Node 4" }, position: { x: 500, y: 200 } },
{ id: "5", data: { label: "Node 5" }, position: { x: 750, y: 250 } },
{
id: "6",
data: { label: "Node 6" },
position: { x: 800, y: 300 },
type: "output"
},
{ id: "e1-2", source: "3", target: "2", type: "straight" },
{ id: "e1-3", source: "1", target: "3", type: "default" },
{ id: "e1-4", source: "1", target: "4", type: "default" },
{ id: "e1-5", source: "5", target: "2", type: "step", animated: true },
{ id: "e1-6", source: "1", target: "6", type: "step" }
];
It's not as confusing as it may seem. We've simply created a master node with id
of 1. Notice how I made its type as input
. Node number 2, 3, 4 and 5 are just normal children. As for the 6th one, we made it an output
type.
For connections between the edges, we use the typical source
- target
pair of attributes. One good thing to note is the different lines you get, that comes from the type
of the edge.
Bonus! If you need to make your node or edge type, look at this example.
Here's the entire Sandbox of the above example:
Top comments (17)
Great tutorial ! My question is how to add logic to our nodes like api calls node,
if-else nodes, show message, send some message to whatsapp.
Because I want to build message automation app
Pls help :)
Hello! Thanks for reading.
I am not active here for quite some time and havenβt used this library much, so I can't answer your question.
Please look at their docs, support, or community (if any). I hope you understand. Thanks!
Great library! Been playing with it for a while. How do we save and restore custom nodes? Any ideas?
Saving and restoring plain default nodes work. Ref - reactflow.dev/examples/save-and-re...
I donβt know much about saving and restoring custom nodes for this. Maybe you can start a new issue in its repo?
Thanks Vaibhav for your quick response. I've figured out the way to achieve the functionality. FYI, you can create custom nodes and register the names with ReactFlow component and use the same name as the node type to be able to save and restore custom components. You can refer this link to get a clearer picture of what I was talking about - reactflow.dev/examples/custom-node/
Look out for ColorSelectorNode.js and setElements() function usage
Nice, thanks for sharing!
Great post! π Iβve also been working with React Flow, and itβs been a game-changer for building interactive node-based graphs. If anyone is interested in seeing another use case, check out ChartDB (github.com/chartdb/chartdb) - we implemented React Flow to visualize database schemas in a unique way. Would love to hear your thoughts and feedback! π
How to avoid overlapping of edges (connection lines) and it's label?
This looks great. Which library do you prefer for automatic node positioning?
actually for automatic position requires the dagre library from npm, for details you can see in the documentation reactflow.dev/examples/layouting/
sorry for my bad english
Thanks for sharing!
Thanks! As for the automatic node positioning I haven't used any such library.
Hey, Nice Article, Keep it up.
Do you anyone have an idea how to use this library on drag and drop imgs (Not just text) ?
Thanks
Thanks for reading!
Not sure of the image support but you can read here that:
The edges overlap all-over, not a great experience.
Can we create custom style node? i have created the node design want to apply as a node but in object how can reaturn? pls guide me
Thanks in Advance
Please take a look at this comment. Thanks!