How do I tell the Masonry component that its cells have changed their height?

喜欢而已 提交于 2019-12-10 17:48:46

问题


I have a react component that displays a one-dimensional list of items in a grid pattern. Every item has the same width and height, and they are located within three columns. There can be a lot of these, so I decided to give react-virtualized a whirl, using the Masonry component, which seems to have been written for precisely this use case. It works well, but for one caveat: If the items change their height, I cannot get Masonry to notice.

Here's a reduced example:

constructor(props) {
    [...]
    this.cellMeasurerCache = new CellMeasurerCache({
        defaultHeight: this.state.height,
        fixedWidth: true,
    });

    this.cellPositioner = createMasonryCellPositioner({
        cellMeasurerCache: this.cellMeasurerCache,
        columnCount: 3,
        columnWidth: 250,
        spacer: 20,
    });
}

[...]

cellRenderer({ index, key, parent, style }) {
    return (
        <CellMeasurer
            cache={this.cellMeasurerCache}
            index={index}
            key={key}
            parent={parent}
        >
            <div style={style}>
                [...]
            </div>
        </CellMeasurer>
    );
}

resetMasonry() {
    this.cellMeasurerCache.clearAll();

    this.cellPositioner.reset({
        cache: this.cellMeasurerCache,
        columnCount: 3,
        columnWidth: 250,
        spacer: 20,
    });

    this.masonryRef.recomputeCellPositions();
}

render() {
    return (
        <AutoSizer>
            {({ height, width }) =>
                <Masonry
                    cellCount={this.state.list.length}
                    cellMeasurerCache={this.cellMeasurerCache}
                    cellPositioner={this.cellPositioner}
                    cellRenderer={this.cellRenderer}
                    height={height}
                    ref={this.setMasonryRef}
                    width={width}
                />
            }
        </AutoSizer>
    );
}

resetMasonry is called when the component's height state has changed. I have cargo-culted the current code from several stackoverflow answers and other resources, even went over the source code, but nothing works. I've noticed that I'm not telling the cellMeasurerCache or anything else about the height change, so I really shouldn't expecting it to work, but there seems to be no way to get that information in there, not even by instantiating a new CellMeasurerCache.

Incidentally, if I change the columnWidth within cellPositioner.reset, the Masonry component updates accordingly, sure enough.

Does anybody know what I'm missing to get it working for a height change? Thanks!


回答1:


If your Masonry cell's sizes change, you need to clear the cached sizes in your CellMeasurerCache and then make sure the cellPositioner is aware of the new sizes also. For example:

// Clear cached measurements since sizes have changed:
cellMeasurerCache.clearAll()

// Let your component know it needs to re-render
this.setState({...}, () => {
  // Assuming you're using the default createCellPositioner()
  // Let it know of any values that may have changed:
  cellPositioner.reset({
    columnCount,
    columnWidth,
    spacer
  })

  // Tell Masonry to discard any cached position data:
  masonryRef.clearCellPositions()
})

You can see a demo of a Masonry component with changing column heights on the RV site just by changing the column width. The source code for that demo is available in the GitHub repo also.

From what you're describing though, I wouldn't suggest using Masonry. I would actually just suggest using a List in a similar way to how I did in this example: http://plnkr.co/edit/zjCwNeRZ7XtmFp1PDBsc?p=preview

The key bit is to calculate the number of items per row dynamically based on the available width, and then you give List an adjusted rowCount:

  const itemsPerRow = Math.floor(width / ITEM_SIZE);
  const rowCount = Math.ceil(ITEMS_COUNT / itemsPerRow);


来源:https://stackoverflow.com/questions/44524350/how-do-i-tell-the-masonry-component-that-its-cells-have-changed-their-height

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!