Adding Component Dynamically in React

Asked

Viewed 1,609 times

1

I’m trying to dynamically add one component inside another in React. So that I click on some element and in onClick it adds this component together to the specified div.

I tried to do it this way: (The object is added but not rendered)

import React from 'react';
import Draggable from 'react-draggable';
import { css } from 'glamor';
import Sortable from 'react-sortablejs';

/**
 *
 */
function getCSS() {
  return {
    square: css({
      width: 100,
      height: 100,
      border: '1px solid #000',
      cursor: 'move',
      display: 'inline-block',
      marginLeft: '10px',
      textAlign: 'center'
    }),
    circle: css({
      width: 100,
      height: 100,
      borderRadius: '50%',
      border: '1px solid #000',
      cursor: 'move',
      display: 'inline-block',
      marginLeft: '10px',
      textAlign: 'center'
    })
  }
}

/**
 *
 */
class DragDuplicate extends React.Component {

  /**
   *
   */
  createSquare() {
    console.log(1);
    document.getElementById('container').append(
      <Draggable>
        <div {...css.square}>Drag</div>;
      </Draggable>
    );
  }

  /**
   *
   */
  createCircle() {
    console.log(2);
    document.getElementById('container').append(
      <Draggable>
        <div {...css.circle}>Drag</div>;
      </Draggable>
    );
  }

  render() {
    let css = getCSS();
    return (
      <div>
        <div {...css.square} onClick={this.createSquare.bind(this)}>Drag</div>
        <div {...css.circle} onClick={this.createCircle.bind(this)}>Drag</div>
        <div {...css.square} onClick={this.createSquare.bind(this)}>Drag</div>
        <div {...css.circle} onClick={this.createCircle.bind(this)}>Drag</div>
        <hr />
        <div id="container"></div>
      </div>
    );
  }
}

export default DragDuplicate;
export { DragDuplicate };

Any example of any doing this would help.

1 answer

1


To render a component react, intentionally cannot use imperative Apis as element.append.

The way is to change yours state to reflect what you want to render using .setState({...}) and use this information to render the changes in the method render(). I don’t know if it works with your use of Draggable etc, but it’s the idea:

class DragDuplicate extends React.Component {
  constructor(props) {
    super(props);
    this.state = {circleShown: false, squareShown: false};
  }    

  createSquare() {
    this.setState({
      squareShown: true,
    });
  }

  createCircle() {
    this.setState({
      circleShown: true,
    });
  }

  renderCircle(css) {
    if (!this.state.circleShown) return null;
    return (
      <Draggable>
        <div {...css.circle}>Drag</div>;
      </Draggable>
    );
  }

  renderSquare(css) {
    if (!this.state.squareShown) return null;
    return (
      <Draggable>
        <div {...css.square}>Drag</div>;
      </Draggable>
    );
  }

  render() {
    let css = getCSS();
    return (
      <div>
        <div {...css.square} onClick={this.createSquare.bind(this)}>Drag</div>
        <div {...css.circle} onClick={this.createCircle.bind(this)}>Drag</div>
        <div {...css.square} onClick={this.createSquare.bind(this)}>Drag</div>
        <div {...css.circle} onClick={this.createCircle.bind(this)}>Drag</div>
        <hr />
        <div id="container">
          {this.renderSquare(css)}
          {this.renderCircle(css)}
        </div>
      </div>
    );
  }
}

Browser other questions tagged

You are not signed in. Login or sign up in order to post.