Im trying to create a reactR/htmlwidgets based package in R, that wraps react-flow.
Im following the official guide from reactR and use the following, but I get errors that I don’t understand.
In the end, I want to replicate the official guide, which has this react code:
import { useCallback } from 'react';
import {
ReactFlow,
MiniMap,
Controls,
Background,
useNodesState,
useEdgesState,
addEdge,
} from '@xyflow/react';
import '@xyflow/react/dist/style.css';
const initialNodes = [
{ id: '1', position: { x: 0, y: 0 }, data: { label: '1' } },
{ id: '2', position: { x: 0, y: 100 }, data: { label: '2' } },
];
const initialEdges = [{ id: 'e1-2', source: '1', target: '2' }];
function Flow() {
const [nodes, setNodes, onNodesChange] = useNodesState(initialNodes);
const [edges, setEdges, onEdgesChange] = useEdgesState(initialEdges);
const onConnect = useCallback((params) => setEdges((eds) => addEdge(params, eds)), [setEdges]);
return (
<ReactFlow
nodes={nodes}
edges={edges}
onNodesChange={onNodesChange}
onEdgesChange={onEdgesChange}
onConnect={onConnect}
>
<MiniMap />
<Controls />
<Background />
</ReactFlow>
);
}
export default Flow;
MWE
create the scaffold
# make sure we have the latest versions available
# install.packages(c("shiny", "devtools", "usethis", "htmlwidgets", "reactR"))
sapply(c("shiny", "devtools", "usethis", "htmlwidgets", "reactR"), packageVersion)
#> $shiny
#> [1] 1 9 1
#>
#> $devtools
#> [1] 2 4 5
#>
#> $usethis
#> [1] 3 1 0
#>
#> $htmlwidgets
#> [1] 1 6 4
#>
#> $reactR
#> [1] 0 6 1
# create the package
usethis::create_package("reactflow")
# getwd() # to check that we are already in reactflow/
# add the react-flow dependency, note @xyflow/react as described here
# https://github.com/xyflow/xyflow/tree/main/packages/react
reactR::scaffoldReactWidget("reactflow", list("@xyflow/react" = "^12.3.5"), edit = FALSE)
system("yarn --version", intern = TRUE)
#> [1] "1.22.19"
system("yarn install") # takes a while...
#> ...
#> success Saved lockfile.
# check the packages
paste(readLines("packages.json"), collapse = "n")
#> {
#> "private": true,
#> "dependencies": {
#> "@xyflow/react": "^12.3.5"
#> },
#> "devDependencies": {
#> "webpack": "^4.27.1",
#> "webpack-cli": "^3.1.2",
#> "@babel/core": "^7.2.0",
#> "babel-loader": "^8.0.4",
#> "@babel/preset-env": "^7.2.0",
#> "@babel/preset-react": "^7.0.0",
#> "css-loader": "^5.0.1",
#> "style-loader": "^2.0.0"
#> },
#> "scripts": {
#> "watch": "webpack --watch",
#> "build": "webpack"
#> }
#> }
system("yarn run webpack")
#> ...
#> Hash: 27f31466a4896d55fa04
#> Version: webpack 4.47.0
#> Time: 9896ms
#> Built at: 11/27/2024 8:26:31 AM
#> Asset Size Chunks Chunk Names
#> reactflow.js 1.06 KiB 0 [emitted] main
#> reactflow.js.map 4.81 KiB 0 [emitted] [dev] main
#> Entrypoint main = reactflow.js reactflow.js.map
#> [0] external "window.reactR" 42 bytes {0} [built]
#> [1] ./srcjs/reactflow.jsx 81 bytes {0} [built]
# I then fix the roxygen tags in R/reactflow.R
devtools::document()
devtools::install(quick = TRUE)
# installs correctly
shiny::runApp()
The MWE app (without react flow) works as expected, hence I suspect I set up everything correctly.
Add react flow
First I want to have a minimal react flow element, which means I change R/reactflow.R to this
reactflow <- function(message, width = NULL, height = NULL, elementId = NULL) {
nodes <- list(
list(id = "1", position = list(x = 0, y = 0), data = list(label = "1")),
list(id = "2", position = list(x = 0, y = 100), data = list(label = "2"))
)
edges <- list(
list(id = "e1-2", source = "1", target = "2")
)
component <- reactR::component(
"reactflow",
list(nodes = nodes, edges = edges)
)
# create widget
htmlwidgets::createWidget(
name = 'reactflow',
component,
width = width,
height = height,
package = 'ReactFlowR',
elementId = elementId
)
}
and srcjs/reactflow.jsx to
import { ReactFlow } from '@xyflow/react';
import '@xyflow/react/dist/style.css';
import { reactWidget } from 'reactR';
reactWidget('reactflow', 'output', ReactFlow);
now, running devtools::document(); devtools::install(quick = TRUE); shiny::runApp() builds everything correctly, but the app does not work anymore.
Instead I see an empty element where the reactflow should be, and when I look at the JS console, I see the following error

I reran the yarn install and yarn run webpack but get another error:
ERROR in ./node_modules/@xyflow/react/dist/esm/index.js
Module not found: Error: Can't resolve 'react/jsx-runtime' in '.../node_modules/@xyflow/react/dist/esm'
Note this issue suggests upgrading to React 18 should fix it, but reactR:::react_version() reports 18.2 already and I am using @xyflow/react version 12.3.5.
I also tried to configure webpack.config.js with this
resolve: {
alias: {
"react/jsx-dev-runtime": "react/jsx-dev-runtime.js",
"react/jsx-runtime": "react/jsx-runtime.js"
}
}
but got the same error.
Any idea how I can start fixing this?