plotly / react-cytoscapejs

React component for Cytoscape.js network visualisations
MIT License
483 stars 68 forks source link

Elements prop is unable to accept objects #2

Closed xhluca closed 6 years ago

xhluca commented 6 years ago

Description

I tried to work through a few examples, and one problem that came up was that the element prop of the react version only accepts an array of objects, whereas the original implementation accepts both arrays and objects. Particularly, objects contain specifications for nodes and edges, for example:

{
"nodes": [{...}, {...}, ..., {...}],
"edges": [{...}, {...}, ..., {...}]
}

Whereas the only format accepted (for the element prop) is the following:

[
{"data": {...}, "position": {...}, ...},
{"data": {...}, "position": {...}, ...},
...
{"data": {...}, "position": {...}, ...}
]

Here's an example of elements in the object (1st) format

Here's an example of elements in the list (2nd) format.

Files

data.json is directly downloaded from the tokyo railway example

App.js is written as such:

import React, { Component } from 'react';
import CytoscapeComponent from './react-cytoscapejs/src/component.js';
import data from './data.json'

class App extends Component {
  constructor(props) {
        super(props);
    }

    render() {
        return <CytoscapeComponent
            elements={data.elements}
        />
    }
}

export default App;

Error Output

The console output error is:

Uncaught TypeError: arr.forEach is not a function
    at forEach (json.js:5)
    at patchElements (patch.js:86)
    at patch (patch.js:12)
    at component.js:43
    at Core.batch (cytoscape.cjs.js:13675)
    at CytoscapeComponent.updateCytoscape (component.js:42)
    at CytoscapeComponent.componentDidMount (component.js:34)
    at commitLifeCycles (react-dom.development.js:14684)
    at commitAllLifeCycles (react-dom.development.js:15904)
    at HTMLUnknownElement.callCallback (react-dom.development.js:145)
    at Object.invokeGuardedCallbackDev (react-dom.development.js:195)
    at invokeGuardedCallback (react-dom.development.js:248)
    at commitRoot (react-dom.development.js:16074)
    at completeRoot (react-dom.development.js:17462)
    at performWorkOnRoot (react-dom.development.js:17390)
    at performWork (react-dom.development.js:17294)
    at performSyncWork (react-dom.development.js:17266)
    at requestWork (react-dom.development.js:17154)
    at scheduleWork (react-dom.development.js:16948)
    at scheduleRootUpdate (react-dom.development.js:17636)
    at updateContainerAtExpirationTime (react-dom.development.js:17663)
    at updateContainer (react-dom.development.js:17690)
    at ReactRoot../node_modules/react-dom/cjs/react-dom.development.js.ReactRoot.render (react-dom.development.js:17956)
    at react-dom.development.js:18096
    at unbatchedUpdates (react-dom.development.js:17517)
    at legacyRenderSubtreeIntoContainer (react-dom.development.js:18092)
    at Object.render (react-dom.development.js:18151)
    at Object../src/index.js (index.js:7)
    at __webpack_require__ (bootstrap fe0e27dab2a44bac186c:678)
    at fn (bootstrap fe0e27dab2a44bac186c:88)
    at Object.0 (registerServiceWorker.js:117)
    at __webpack_require__ (bootstrap fe0e27dab2a44bac186c:678)
    at ./node_modules/ansi-regex/index.js.module.exports (bootstrap fe0e27dab2a44bac186c:724)
    at bootstrap fe0e27dab2a44bac186c:724
index.js:2178 The above error occurred in the <CytoscapeComponent> component:
    in CytoscapeComponent (at App.js:11)
    in App (at src/index.js:7)

Consider adding an error boundary to your tree to customize error handling behavior.
Visit https://fb.me/react-error-boundaries to learn more about error boundaries.

Here is the screenshot of react app output: capture1 capture2 capture3 capture 4

Reproducing Error

Steps toward reproducing the error in command line:

# Create the app
npx create-react-app cytoscape
cd cytoscape

# Add dependencies
yarn add cytoscape
cd src
git clone https://github.com/plotly/react-cytoscapejs.git

# Here, replace App.js with the file described in the issue.
# Also add data.json if required

cd ..
yarn build
yarn start
maxkfranz commented 6 years ago

This is expected behaviour. While the core lib accepts either the [] or { nodes: [], edges: [] } formats, the [] format is preferred. This is consistent with the formats used in other parts of the core lib's API --- the { nodes: [], edges: [] } format isn't allowed anywhere except the initialisation JSON. Eventually, the { nodes: [], edges: [] } format will be deprecated, and then it will be removed altogether in Cytoscape v4.

So this React component only supports the preferred [] format.

The Tokyo railway example had its JSON generated from an export from the Cytoscape Java desktop app. Unfortunately, the Java JSON exporter isn't up-to-date and it uses the old format. However, that is something that the Cytoscape Consortium is working on.

xhluca commented 6 years ago

That makes sense, thank you! I'll try out the updated examples by the Consortium once they solved the problem!

maxkfranz commented 6 years ago

@xhlulu After further analysis, it may not be practical to drop support for the { nodes: [], edges: [] } format in the future -- given the number of old JSON files that users have created. I've created a utility function to help with these old files: Component.normalizeElements()

You can try it in v1.1.0