3 votes

Comment puis-je indiquer au composant Masonry que la hauteur de ses cellules a changé?

J'ai un composant react qui affiche une liste unidimensionnelle d'éléments dans un motif de grille. Chaque élément a la même largeur et hauteur, et ils sont situés dans trois colonnes. Il peut y en avoir beaucoup, donc j'ai décidé d'essayer react-virtualized, en utilisant le composant Masonry, qui semble avoir été écrit précisément pour ce cas d'utilisation. Ça marche bien, mais avec un hic : Si les éléments changent de hauteur, je ne peux pas faire en sorte que Masonry le remarque.

Voici un exemple simplifié :

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 (

                [...]

    );
}

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

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

    this.masonryRef.recomputeCellPositions();
}

render() {
    return (

            {({ height, width }) =>

            }

    );
}

resetMasonry est appelé lorsque l'état de hauteur du composant a changé. J'ai copié-collé le code actuel de plusieurs réponses de stackoverflow et d'autres ressources, j'ai même parcouru le code source, mais rien ne fonctionne. J'ai remarqué que je n'incluais pas le cache cellMeasurerCache ou autre de la hauteur, donc je ne devrais pas m'attendre à ce que cela fonctionne réellement, mais il semble qu'il n'y a pas de moyen d'obtenir cette information, même en instanciant un nouveau CellMeasurerCache.

Par ailleurs, si je change la columnWidth dans cellPositioner.reset, le composant Masonry se met à jour en conséquence, c'est sûr.

Est-ce que quelqu'un sait ce que j'oublie pour le faire fonctionner en cas de changement de hauteur ? Merci !

6voto

brianvaughn Points 494

Si les tailles des cellules de votre Masonry changent, vous devez effacer les tailles mises en cache dans votre CellMeasurerCache et vous assurer que le cellPositioner est également au courant des nouvelles tailles. Par exemple:

// Effacer les mesures mises en cache car les tailles ont changé :
cellMeasurerCache.clearAll()

// Informez votre composant qu'il doit se réexécuter
this.setState({...}, () => {
  // En supposant que vous utilisez le createCellPositioner() par défaut
  // Informez-le de toute valeur qui aurait pu changer :
  cellPositioner.reset({
    columnCount,
    columnWidth,
    spacer
  })

  // Dites à Masonry de supprimer toute donnée de position mise en cache :
  masonryRef.clearCellPositions()
})

Vous pouvez voir une démo d'un composant Masonry avec des hauteurs de colonne qui changent sur le site RV en modifiant simplement la largeur de la colonne. Le code source de cette démo est disponible dans le dépôt GitHub aussi.

Cependant, d'après ce que vous décrivez, je ne recommanderais pas d'utiliser Masonry. Je vous suggérerais en fait d'utiliser simplement une List de manière similaire à ce que j'ai fait dans cet exemple: http://plnkr.co/edit/zjCwNeRZ7XtmFp1PDBsc?p=preview

La clé est de calculer le nombre d'éléments par ligne dynamiquement en fonction de la largeur disponible, puis vous donnez à List un rowCount ajusté :

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

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X