How to create dynamic material-ui elements in a react app?

Viewed 65

I am trying to create a dynamic mui grid element when a button is pressed in a react component. When I tried to create let newGrid = document.createElement('Grid') it does not work as a normal div creation.

Any suggestions?

Current code snippet:

return (
    <>
        <button onClick={addRow}>Add Row</button>
        <Grid container className='v-timeline-container'>
            <Grid xs={12} item className="v-timeline-item v-center v-border">
                <TextItems />
            </Grid>
        </Grid>

    </>
   
)

What I am trying to achieve dynamically:

return (
    <>
        <button onClick={addRow}>Add Row</button>
        <Grid container className='v-timeline-container'>
            <Grid xs={12} item className="v-timeline-item v-center v-border">
                <TextItems />
            </Grid>
            <Grid xs={12} item className="v-timeline-item v-center v-border">
                <TextItems />
            </Grid>
        </Grid>

    </>
   
)
  
2 Answers

React uses a VDOM to keep track of stuff internally, you manipulating the DOM directly using DOM APIs is considered dangerous. What you should do this something like this.

function App(){
 // you probably want to track the text items in each row, 
 // so use an array of objects
 const [gridItems, setGridItems] = useState([]);

 // this function adds a new grid item
 const onClick = () => {
  setGridItems([...gridItems, {text: "new row", id: gridItems.length + 1}]);
 };

 return (
    <>
         <button onClick={onClick}>Add Row</button>
         <Grid container className='v-timeline-container'>
          {
            gridItems.map(item => (
             <Grid xs={12} item className="v-timeline-item v-center v-border">
                <TextItems>{item.text}</TextItems>
             </Grid>
            ))
          }
         </Grid>
    </>
 );
}

Using setState is a solution. It increments a number in state to create an array from it. In your case you will certainly push new data to an array when you click on the button. But you get the idea.

import React, { useState } from 'react';
import { Grid } from '@mui/material'

const ListItems = () => {
  const [items, setItems] = useState(1);
  
  const addRow = () => {
    setItems((prev) => prev + 1)
  }

  return (
    <>
        <button onClick={addRow}>Add Row</button>
        <Grid container className='v-timeline-container'>
            {
              [...Array(items).keys()].map((key) => (
                <Grid xs={12} item className="v-timeline-item v-center v-border">
                  <p>{key + 1} row</p>
                </Grid>
              ))
            }
        </Grid>

    </>
  )
 }

export default ListItems

Related