javascriptreactjskonvajskonvajs-reactjs

Rendering objects dynamically with KonvaJs-ReactJs


I want to render an array of React components with the help of KonvaJs without knowing exactly which object I draw at a particular moment. To be more specific, here is my code:

One of the React components I want to render, wall.js:

class CWall extends React.Component {
 render() {
    return (
      <React.Fragment>
        <Rect /*some props*/></Rect>
        <Transformer /*some props*/></Transformer>
      </React.Fragment>
    )
  }
}

In the other component I create CWall when the button is clicked, planmenu.js:

class PlanMenu extends React.Component {
  render() {
    ...
    return (
    ...
        <button type="button"
          onClick={() => { addObject(
            new CWall({
                x: 100,
                y: 100,
                length: 200
            }))}}>Wall
        </button>
    )
  }
}

The created objects are passed to the component which should display them, planbuilder.js:

import CWall from './objects/wall'

class PlanBuilder extends React.Component {
  render() {
    const { objects } = this.props
    return (
      <Stage>
        <Layer>
          {
            objects.map(function(object) {
              var ObjectType = object.constructor.name;
              /* the following line gives an error to me */
              return <ObjectType {...object.props} key={object.id} />;
            }, this)
          }
        </Layer>
      </Stage>
    );
  }
}

The specified line throws an error:

konva has no node with the type CWall

However, if I render one CWall directly, I get it on the screen as expected. It seems to me like evidence that konva is able to render CWall objects:

class PlanBuilder extends React.Component {
  render() {
    const { objects } = this.props
    return (
      <Stage>
        <Layer>
          <CWall x={100} y={100} length={200} />
        </Layer>
      </Stage>
    );
  }
}

So my question is: what is the proper way of rendering objects without knowing their exact types? Thank you in advance.


Solution

  • In general, you should not add React components directly into the state. Instead, just add pure data about your app, and then just render from that data. It can be like this:

    class PlanMenu extends React.Component {
      render() {
        ...
        return (
        ...
            <button type="button"
              onClick={() => { addObject({ x: 10, y: 10, type: 'wall' })}}
            </button>
        )
      }
    }
    
    
    import CWall from './objects/wall'
    
    
    const TYPES = {
       'wall' : CWall
    };
    
    class PlanBuilder extends React.Component {
      render() {
        const { objects } = this.props
        return (
          <Stage>
            <Layer>
              {
                objects.map(function(object) {
                  const Component = TYPES[object.type];
                  return <Component {...object} key={object.id} />;
                }, this)
              }
            </Layer>
          </Stage>
        );
      }
    }