首页 > 解决方案 > Masonic React.js:Left Nav 的宽度滚动问题

问题描述

在此处输入图像描述

import * as React from 'react';
    import {
      Card,
      CardBody,
      CardLink,
      CardImg,
      CardTitle,
      CardText,
    } from 'reactstrap';
    import {useWindowSize} from '@react-hook/window-size';
    import {
      useMasonry,
      usePositioner,
      useContainerPosition,
      useScroller,
    } from 'masonic';
    
    const Gallery = ({items}) => {
      const containerRef = React.useRef(null);
      let [windowWidth, height] = useWindowSize();
      windowWidth = windowWidth - (0.3*windowWidth);
      const {offset, width} = useContainerPosition(containerRef, [
        windowWidth,
        height,
      ]);
      const positioner = usePositioner({width, columnGutter: 8});
      const {scrollTop, isScrolling} = useScroller(offset);
    
      const NatureCard = ({
        index,
        data: {image = '', displayName, description = '', link = ''},
        width,
      }) => (
        <div>
          <Card>
            <CardImg src={image} />
            <CardTitle tag="h5">{displayName}</CardTitle>
            <CardText>{description}</CardText>
            {link && <CardLink href={link}>View</CardLink>}
          </Card>
        </div>
      );
    
      return (
        <div>
          {useMasonry({
            positioner,
            scrollTop,
            isScrolling,
            height,
            containerRef,
            items: items,
            overscanBy: 3,
            rowGutter: 10,
            render: NatureCard,
          })}
        </div>
      );
    };
    
    export default Gallery;

我正在使用共济会及以上代码,但是我的数据在宽度而不是高度上被重新排列得很奇怪

正在使用的库:https ://codesandbox.io/s/masonryscroller-example-hb3qj

编辑:我认为问题在于我如何检索我的物品

这里的代码沙盒: https ://codesandbox.io/s/masonryscroller-example-hb3qj ?file=/src/index.js

标签: reactjsmasonry

解决方案


问题是当浏览器获取图像时,卡片的高度会发生变化,因此应该重新计算它们的位置。这是通过useResizeObserver创建一个调整大小的观察者来完成的,当对影响其高度的单元格进行突变时,该观察者会强制更新网格单元格的位置。现在,每当您调整组件大小时,它都会正确呈现。初始渲染中还有另一个问题width是 0,因此项目没有正确定位。我用作windowWidth占位符,直到设置宽度。

您可以在文档中查看它:https ://github.com/jaredLunde/masonic#useresizeobserverpositioner

asnwer CodeSandbox

答案:

import React from "react";
import ReactDOM from "react-dom";
import { useWindowSize } from "@react-hook/window-size";
import { Card, CardImg, CardText, CardTitle } from "reactstrap";
import { styles } from "./theme";
import {
  useMasonry,
  usePositioner,
  useContainerPosition,
  useScroller,
  // import this
  useResizeObserver
} from "masonic";

const App = () => {
  const containerRef = React.useRef(null);
  let [windowWidth, windowHeight] = useWindowSize();
  const { offset, width } = useContainerPosition(containerRef, [
    windowWidth,
    windowHeight
  ]);
  // the width is equal to windowWidth - scroll bar width (17px in chrome)
  console.log(width, windowWidth);
  const positioner = usePositioner({
    // Use windowWidth as a placeholder if container width is 0 which causes positioning problems
    // This happens in initial render then width will be used
    width: width || windowWidth,
    columnGutter: 10
  });
  // This hook creates a resize observer that forces updates to the grid
  // cell positions when mutations are made to cells affecting their height.
  const resizeObserver = useResizeObserver(positioner);
  const { scrollTop, isScrolling } = useScroller(offset);

  return (
    <main>
      <div>
        {useMasonry({
          positioner,
          scrollTop,
          isScrolling,
          height: windowHeight,
          containerRef,
          items: items,
          render: NatureCard,
          // use it here
          resizeObserver
        })}
      </div>
      <Header />
    </main>
  );
};

const NatureCard = ({
  index,
  data: { image = "", displayName, description = "Hello", link = "" },
  width,
  height
}) => (
  <Card>
    <CardImg src={image} />
    <CardTitle tag="h5">{displayName}</CardTitle>
    <CardText>{description}</CardText>
  </Card>
);

const Header = () => {
  // const scrollY = useWindowScroll(5);
  return (
    <h1>
      <span role="img" aria-label="bricks">
        
      </span>{" "}
      MASONIC
    </h1>
  );
};

const items = [
  {
    image:
      "https://hips.hearstapps.com/hmg-prod.s3.amazonaws.com/images/gettyimages-647727888-master-1506626232.jpg",
    displayName: "QUIZ: Has Reese Witherspoon Smooched These Guys On-Screen?"
  },
  {
    image:
      "https://ichef-1.bbci.co.uk/news/320/cpsprodpb/97BE/production/_98064883_ikea.jpg",
    displayName: "Ikea buys odd jobs firm TaskRabbit"
  },
  {
    image:
      "https://cdn.theatlantic.com/assets/media/img/mt/2017/09/ra_3000x3000-4/facebook.jpg",
    displayName:
      "Radio Atlantic: Russia! Live with Julia Ioffe and Eliot A. Cohen"
  },
  {
    image: "https://i.redd.it/th5enkjgumoz.jpg",
    displayName: "Bar"
  },
  {
    image: "https://imgur.com/lvK8Faf.jpg",
    displayName:
      "'Cancer patient' finds lump was toy traffic cone inhaled in 1977 | UK news"
  },
  {
    image: "https://i.imgur.com/e89Pb8j.gif",
    displayName: "It's cool bro, I got this"
  },
  {
    image: "https://i.redd.it/336erdiy5moz.jpg",
    displayName: "Reddit"
  },
  {
    image:
      "https://hips.hearstapps.com/hmg-prod.s3.amazonaws.com/images/img-5675-jpg-1506621753.jpg",
    displayName:
      "Prepare to Geek Out Over This Adorable Game of Thrones Wedding Shower"
  },
  {
    image:
      "https://venturebeat.com/wp-content/uploads/2017/03/ShopChat-e1506572472915.jpg",
    displayName: "Effective chatbots master conversational size and fit"
  },
  {
    image:
      "https://hips.hearstapps.com/hmg-prod.s3.amazonaws.com/images/gettyimages-647727888-master-1506626232.jpg",
    displayName: "QUIZ: Has Reese Witherspoon Smooched These Guys On-Screen?"
  },
  {
    image:
      "https://ichef-1.bbci.co.uk/news/320/cpsprodpb/97BE/production/_98064883_ikea.jpg",
    displayName: "Ikea buys odd jobs firm TaskRabbit"
  },
  {
    image:
      "https://cdn.theatlantic.com/assets/media/img/mt/2017/09/ra_3000x3000-4/facebook.jpg",
    displayName:
      "Radio Atlantic: Russia! Live with Julia Ioffe and Eliot A. Cohen"
  },
  {
    image: "https://i.redd.it/th5enkjgumoz.jpg",
    displayName: "Bar"
  },
  {
    image: "https://i.imgur.com/HjgUCHF.png",
    displayName:
      "'Cancer patient' finds lump was toy traffic cone inhaled in 1977 | UK news"
  },
  {
    image: "https://i.imgur.com/e89Pb8j.gif",
    displayName: "It's cool bro, I got this"
  },
  {
    image: "https://i.redd.it/336erdiy5moz.jpg?4",
    displayName: "Reddit"
  },
  {
    image:
      "https://hips.hearstapps.com/hmg-prod.s3.amazonaws.com/images/img-5675-jpg-1506621753.jpg",
    displayName:
      "Prepare to Geek Out Over This Adorable Game of Thrones Wedding Shower"
  },
  {
    image:
      "https://venturebeat.com/wp-content/uploads/2017/03/ShopChat-e1506572472915.jpg",
    displayName: "Effective chatbots master conversational size and fit"
  },
  {
    image: "https://i.imgur.com/e89Pb8j.gif",
    displayName: "It's cool bro, I got this"
  },
  {
    image: "https://i.redd.it/336erdiy5moz.jpg?4",
    displayName: "Reddit"
  },
  {
    image:
      "https://hips.hearstapps.com/hmg-prod.s3.amazonaws.com/images/img-5675-jpg-1506621753.jpg",
    displayName:
      "Prepare to Geek Out Over This Adorable Game of Thrones Wedding Shower"
  }
];

ReactDOM.render(<App />, document.getElementById("root"));

推荐阅读