Skip to content

Layout is not respected when passed by props #870

@tlegluhe

Description

@tlegluhe

Hello !
I am encountering a problem with RGL and I don't know if it's a bug or me doing things badly.
Demo here

What I'm trying to do

I'd like to create a dashboard using react-grid-layout. I'm trying to implement the container pattern so I have a DashboardContainer component controlling the layout via his state and passing this layout down to a Dashboard component in the props.

The problem I encounter

Elements are placed correctly for the initial state but when I add items, the x, y, w and h of the added element aren't correct.
It should be (5,0,2,2) for the first addition, and it ends up being placed on (0,4,1,1)
I saw that elements can be redimensionned to 1 of width and height if they don't have the correct key, but I think my keys are correct.

Example: this layout is passed to Dasboard

image

But this is the displayed layout (the element "new0" isn't corresponding)

image

My code

Dashboard Container :

import React from "react";
import ReactDOM from "react-dom";
import Dashboard from "./Dashboard";

class DashboardContainer extends React.Component {
  static defaultProps = {
    maxRows: 8,
    cols: 12
  };

  state = {
    layout: [
      { i: "key0", x: 0, y: 0, w: 2, h: 2 },
      { i: "key1", x: 2, y: 0, w: 3, h: 2 },
      { i: "key2", x: 2, y: 2, w: 2, h: 2 },
      { i: "key3", x: 8, y: 0, w: 3, h: 2 }
    ],
    newElementsCount: 0
  };

  onLayoutChange = l => {
    this.setState({ layout: l });
  };

  add = () => {
    // all this is just to calculate where the new element should be placed
    var x = 0,
      y = 0,
      w = 2,
      h = 2,
      arr = [],
      trouve = false;
    for (let i = 0; i < 12; i++) {
      arr.push([]);
      for (let j = 0; j < 8; j++) {
        arr[i].push(1);
      }
    }
    this.state.layout.forEach(function(e) {
      for (let i = 0; i < e.w; i++) {
        for (let j = 0; j < e.h; j++) {
          arr[e.x + i][e.y + j] = 0;
        }
      }
    });
    var checkOk = (arr, w, h, x, y) => {
      var res = true;
      for (let i = x; i < x + w; i++) {
        for (let j = y; j < y + h; j++) {
          if (!arr[i][j]) res = false;
        }
      }
      return res;
    };
    if (checkOk(arr, w, h, x, y)) trouve = true;

    while (!trouve && y + h <= 8) {
      if (x + w === 12) {
        x = 0;
        y++;
      } else {
        x++;
      }
      if (checkOk(arr, w, h, x, y)) trouve = true;
    }
    if (trouve) {
      var newLayout = this.state.layout;

      newLayout.push({
        i: "new" + this.state.newElementsCount,
        x: x,
        y: y,
        w: w,
        h: h
      });

      this.setState({
        newElementsCount: this.state.newElementsCount + 1,
        layout: newLayout
      });
    } else {
      console.log("Can't add");
    }
  };

  render() {
    return (
      <div>
        <Dashboard
          layout={this.state.layout}
          add={this.add}
          cols={this.props.cols}
          maxRows={this.props.maxRows}
          onLayoutChange={this.onLayoutChange}
          preventCollision={true}
        />
      </div>
    );
  }
}

const contentDiv = document.getElementById("root");
ReactDOM.render(React.createElement(DashboardContainer), contentDiv);

Dashboard :

import React from "react";
import RGL, { WidthProvider } from "react-grid-layout";
const ReactGridLayout = WidthProvider(RGL);

class Dashboard extends React.Component {
  generateDOM() {
    return this.props.layout.map(function(item) {
      return <div key={item.i}>{item.i}</div>;
    });
  }

  render() {
    return (
      <div>
        <button onClick={this.props.add}>Add</button>
        <ReactGridLayout
          rowHeight={30}
          maxRows={this.props.maxRows}
          cols={this.props.cols}
          layout={this.props.layout}
          compactType={null}
          onLayoutChange={this.props.onLayoutChange}
        >
          {this.generateDOM()}
        </ReactGridLayout>
      </div>
    );
  }
}

module.exports = Dashboard;

You can find a codesandbox with this exact code here

I'm still very new to React and RGL so any suggestions are welcome !

Thank you

Metadata

Metadata

Assignees

No one assigned

    Labels

    staleThe label to apply when a pull request or an issue is stale

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions