Search code examples
reactjsstyles

position element dynamically after a render react js


So I have an app in reactjs and all I want to do is just dynamically position elements. The app is for adding rooms.
This is the App component (not sure you need this part):

import React, { useState } from "react";
import { BrowserRouter as Router, Switch, Route } from "react-router-dom";
import HomePage from "./HomePage";
import Header from "./Header";
import AddRoom from "./AddRoom";
import Footer from "./Footer";
import Room from "./Room";

function App() {
  const [rooms, setRooms] = useState([]);

  function updateRooms(room) {
    setRooms((prevRooms) => {
      return [...prevRooms, room];
    });
  }

  return (
    <div className="App">
      <Router>
        <Header />
        <Route
          exact
          path="/"
          component={() => {
            return <HomePage rooms={rooms} />;
          }}
        />
        <Route
          exect
          path="/AddRoom"
          component={() => {
            return <AddRoom addRoom={updateRooms} />;
          }}
        />
        <Footer />
      </Router>
    </div>
  );
}

export default App;

I also have a HomePage component and in this HomePage component I am rendering Room components:

import React from "react";
import AddCircleIcon from "@material-ui/icons/AddCircle";
import { Link } from "react-router-dom";
import Room from "./Room";

function HomePage(props) {
  return (
    <div className="center top-padding">
      <h1>Hey There!</h1>
      <p>Start adding rooms</p>
      <Link to="/AddRoom">
        <button className="btn-icon">
          <AddCircleIcon style={{ color: "white" }} />
        </button>
      </Link>
      <div className="container">
        <div className="row">
          {props.rooms.map((room, index) => {
            return (
              <Room
                key={index}
                id={index}
                name={room.name}
                type={room.type}
                color={room.color}
              />
            );
          })}
        </div>
      </div>
    </div>
  );
}

export default HomePage;

and this is the Room component:

import React, { useState } from "react";

function Room(props) {
  var unit = 1;
  var pixel = 100;
  var column = 1;
  const [mesures, setMesures] = useState({
    unit: 1,
    pixel: 100,
    column: 1
  });

  function posStyle() {
    debugger;
    if (column == 12) {
      setMesures((prevMesures) => {
        return {
          ...prevMesures,
          unit: 1,
          pixel: 100,
          column: 1
        };
      });
      return <br />;
    } else return null;
  }

  function increase() {
    debugger;
    setMesures((prevMesures) => {
      return {
        ...prevMesures,
        unit: [unit++],
        pixel: [unit * 100],
        column: [column++]
      };
    });
  }
  return (
    <div
      className={"room-border col-" + column}
      style={{ backgroundColor: props.color, marginLeft: pixel + "px" }}
    >
      {props.type}
      {props.name}
      {posStyle}
      {increase}
    </div>
  );
}

export default Room;

So my question is about the Room component that rendered in the HomePage Component. I want which element(room) in HomePage to display in a line of 12 rooms and then after line 12 to break point to a new line

like so: https://prnt.sc/13dyytk

But instead it is all shown as one element because the mesures state is not changing. Now I understand why it is not changing because the page is always re-rendering so is there any other solution so I can display those elements?

in case you need css:

.App {
  font-family: sans-serif;
}

.top-padding {
  padding-top: 100px;
}

body {
  background-image: url("backGround.jpg");
  color: white;
}

.logo {
  font-size: 30px;
  padding-bottom: 50px;
}
.btn-icon {
  padding: 0;
  border: none;
  outline: none;
  background: none;
}

.center {
  text-align: center;
}

footer {
  position: absolute;
  text-align: center;
  bottom: 0;
  width: 100%;
  height: 2.5rem;
}

.error {
  color: red;
  margin-top: 5px;
}

.room-border {
  border: solid;
  width: 75px;
  height: 35px;
  margin-top: 10px;
  position: absolute;
}

.room-container {
  text-align: center;
}


Solution

  • Use CSS Grid. You can do something like this

    Add this to your CSS

    .container {
      display: grid;
      grid-template-columns: repeat(12, minmax(0, 1fr));
      column-gap: 1rem;
    }
    

    And for your room components

    <div className="container">
          {props.rooms.map((room, index) => {
            return (
              <Room
                key={index}
                id={index}
                name={room.name}
                type={room.type}
                color={room.color}
              />
            );
          })}
      </div>