brianzinn / react-babylonjs

React for Babylon 3D engine
https://brianzinn.github.io/react-babylonjs/
812 stars 102 forks source link

change <rowDefinition/> and <columnDefinition/> childrens doesn't reset on component update #237

Closed saidmoya12 closed 1 year ago

saidmoya12 commented 1 year ago

(row and column definition aren't reset on component update)

When I update rowDefinition and or columnDefinition this add a new column for each update

This is my code

<grid ref={RGrid} >
  {Array.from(Array(rows).keys()).map((_, rowIndex) => ( {/*create rows*/}
    <rowDefinition key={rowIndex} value={rowScale} />
  ))}
  {Array.from(Array(columns).keys()).map((_, colIndex) => (
    <columnDefinition key={colIndex} value={columnScale} />{/*create cols*/}
  ))}
  {children}
</grid>

I try to set with useEffect but children is cleared too :(

useEffect(() => {
  //clear previous
  for (let r = 0; r < RGrid.current.rowCount; r++) {
    RGrid.current.removeRowDefinition(r)
  }
  for (let c = 0; c < RGrid.current.columnCount; c++) {
    RGrid.current.removeColumnDefinition(c)
  }
  //set new column definition
  for(let i = 0; i < rows; i++) {
    RGrid.current.addRowDefinition(rowScale)
  }
  for(let j = 0; j < rows; j++) {
    RGrid.current.addColumnDefinition(columnScale)
  }
}, [columns, rows])

<grid ref={RGrid}>
   {children}
</grid>

Any idea to update a grid?

Thanks!

brianzinn commented 1 year ago

hi @saidmoya12 - thanks for finding that. I never got that far in using the grid, but I think if we add a method telling the column how to remove itself then it will work - just need to add some code here: https://github.com/brianzinn/react-babylonjs/blob/master/packages/react-babylonjs/src/customHosts/grid/columnDefinition.ts

Can you provide a repro?

saidmoya12 commented 1 year ago

Thanks, but columnDefinition and rowDefinition must be cleared from grid component (parent) once only, however I found a solution!

We can force remount component just modifying key prop when columns or rows are modified

key={`${columns}-${rows}`}

<grid ref={RGrid} key={`${columns}-${rows}`}> {/*remount component if columns or row are different*/}
  {Array.from(Array(rows).keys()).map((_, rowIndex) => ( {/*define rows*/}
    <rowDefinition key={rowIndex} value={rowScale} />
  ))}
  {Array.from(Array(columns).keys()).map((_, colIndex) => (
    <columnDefinition key={colIndex} value={columnScale} />{/*define cols*/}
  ))}
  {children}
</grid>

Thanks again brianzinn

brianzinn commented 1 year ago

That's kind of a hack as it will create a new Grid (certainly a useful hack) as you are essentially tricking the reconciler to rebuild everything. If you get to the point where you want to keep the grid I'm happy to add in the removeXxxDefinition(...) when the definitions are removed.

Thanks for following up and sharing your workaround.