flowhub / the-graph

SVG custom elements for FBP graph editing and visualization. Used in noflo/noflo-ui
https://flowhub.github.io/the-graph/demo-full.html
MIT License
1.01k stars 180 forks source link

Cannot read properties of undefined (reading 'length') #622

Open linonetwo opened 11 months ago

linonetwo commented 11 months ago
Cannot read properties of undefined (reading 'length')
TypeError: Cannot read properties of undefined (reading 'length')
    at eval (webpack-internal:///./node_modules/.pnpm/the-graph@0.13.1_react-dom@18.2.0_react@18.2.0/node_modules/the-graph/the-graph/the-graph-graph.js:489:58)
    at Array.map (<anonymous>)
截屏2023-07-11 19 09 07

only inPorts and outPorts exists on component, no inports, so inports is undefined.

var componentInfo = self.props.library[node.component];

        if (TheGraph.config.autoSizeNode && componentInfo) {
          // Adjust node height based on number of ports.
          var portCount = Math.max(componentInfo.inports.length, componentInfo.outports.length);

I get library by this, there is no doc on this, I read the source to learn this:

/* eslint-disable @typescript-eslint/strict-boolean-expressions */
/* eslint-disable @typescript-eslint/promise-function-async */
import { useThemeObservable } from '@services/theme/hooks';
import { type Graph, loadJSON } from 'fbp-graph/lib/Graph';
import { ComponentLoader } from 'noflo';
import { useEffect, useState } from 'react';
import { useTranslation } from 'react-i18next';
import type { IFBPLibrary } from 'the-graph';
import { GraphEditor } from './GraphEditor';
import { photoboothJSON } from './photobooth.json';

export default function Workflow(): JSX.Element {
  const { t } = useTranslation();
  const theme = useThemeObservable();

  const [library, setLibrary] = useState<IFBPLibrary | undefined>();
  const [graph, setGraph] = useState<Graph | undefined>();
  useEffect(() => {
    void loadJSON(photoboothJSON).then(graph => {
      setGraph(graph);
    });
  }, []);
  // load library bundled by webpack noflo-component-loader from installed noflo related npm packages
  useEffect(() => {
    const loader = new ComponentLoader('');
    void loader.listComponents().then((componentList) => {
      const libraryToLoad: IFBPLibrary = {};
      Object.entries(componentList).forEach(([name, componentDefinitionRaw]) => {
        if (typeof componentDefinitionRaw === 'string') {
          // TODO: handle these ComponentDefinition types
          return;
        }
        if ('getComponent' in componentDefinitionRaw) {
          const componentDefinition = componentDefinitionRaw.getComponent();
          libraryToLoad[name] = componentDefinition;
        }
      });
      setLibrary(libraryToLoad);
    });
  }, []);
  return graph && library
    ? (
      <>
        <GraphEditor theme={theme?.shouldUseDarkColors ? 'dark' : 'light'} library={library} graph={graph} />
      </>
    )
    : <div>{t('Loading')}</div>;
}

So library constructed from noflo's new ComponentLoader().listComponents()[0].getComponent() is not assignable to <TheGraph.App />?

linonetwo commented 11 months ago

https://github.com/noflo/noflo-ui/blob/22d26eca71b52cd5181dd253f76bdb13c6bfecd4/src/runtime.js#L25-L33

Why this, can you just replace all inports to inPorts so this is compatible with noflo (which has ts typing?)

linonetwo commented 11 months ago

Who is sending this?

https://github.com/noflo/noflo-ui/blob/22d26eca71b52cd5181dd253f76bdb13c6bfecd4/components/RuntimeReducer.js#L74-L76

Anyone knows? I need to find ts type for componentForLibrary's input, it is not Component from import { Component } from 'noflo'; which only have icon and description but no inPorts

Seem to be this https://github.com/noflo/noflo-runtime-base/blob/36ff1a439e1df9ad7611afd3cda908cce9e14fe2/src/protocol/Component.js#L202-L209

runtime:components is no used anywhere, only runtime:component is used and is send from here.

linonetwo commented 11 months ago

This is wrong

截屏2023-07-12 01 05 35

the component from getComponent() is really a class Component extends EventEmitter, so can't use componentForLibrary on it.