You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何将jQuery实现的Twitter-Masonry联动逻辑转换为React代码?

Solution for React-based Masonry Layout with Loaded Tweets

Hey there! Mixing jQuery and React can definitely lead to headaches with DOM sync and component state, so let's rewrite that logic using React's native patterns—either hooks for functional components or lifecycle methods for class components. Here's how to do it properly:

Key Concepts to Follow

  • Load the Twitter widget script safely without duplicates
  • Listen for Twitter's loaded event (triggers when all embedded Tweets are rendered)
  • Initialize/reflow Masonry only after Tweets are fully loaded
  • Clean up event listeners and Masonry instances to prevent memory leaks

We'll use useEffect to handle script loading and event binding, useRef to access the Masonry container and instance, and ensure proper cleanup:

import { useEffect, useRef } from 'react';
import Masonry from 'masonry-layout'; // Install via npm: npm install masonry-layout

const TweetMasonryGrid = () => {
  const gridContainerRef = useRef(null);
  const masonryInstanceRef = useRef(null);

  useEffect(() => {
    // Step 1: Load Twitter Widget Script (only once)
    const loadTwitterWidget = () => {
      if (document.getElementById('twitter-wjs')) return;
      const script = document.createElement('script');
      script.id = 'twitter-wjs';
      script.src = 'https://platform.twitter.com/widgets.js';
      script.async = true;
      document.body.appendChild(script);
    };

    loadTwitterWidget();

    // Step 2: Set up Twitter event listeners
    const initTwitterEvents = () => {
      window.twttr?.ready((twttr) => {
        const handleTweetsLoaded = () => {
          // Initialize Masonry if it doesn't exist, or reflow if it does
          if (!masonryInstanceRef.current && gridContainerRef.current) {
            masonryInstanceRef.current = new Masonry(gridContainerRef.current, {
              itemSelector: '.grid-item',
              columnWidth: 300,
              gutter: 20
            });
          } else {
            masonryInstanceRef.current?.layout();
          }
        };

        // Bind the 'loaded' event (fires when all Tweets are rendered)
        twttr.events.bind('loaded', handleTweetsLoaded);

        // Cleanup on component unmount
        return () => {
          twttr.events.unbind('loaded', handleTweetsLoaded);
          masonryInstanceRef.current?.destroy();
        };
      });
    };

    // Wait for the twttr object to be available
    const twttrCheckInterval = setInterval(() => {
      if (window.twttr) {
        clearInterval(twttrCheckInterval);
        initTwitterEvents();
      }
    }, 100);

    // Cleanup interval if component unmounts before twttr is ready
    return () => {
      clearInterval(twttrCheckInterval);
      masonryInstanceRef.current?.destroy();
    };
  }, []);

  return (
    <div ref={gridContainerRef} className="grid">
      {/* Your Masonry grid items with embedded Tweets */}
      <div className="grid-item">
        <blockquote className="twitter-tweet">
          <p lang="en" dir="ltr">This is an example embedded tweet!</p>
          &mdash; Twitter (@Twitter) <a href="https://twitter.com/Twitter/status/1234567890">January 1, 2020</a>
        </blockquote>
      </div>
      {/* Add more grid items here */}
    </div>
  );
};

export default TweetMasonryGrid;

Option 2: Use react-masonry-css (Simpler, React-Friendly Alternative)

If you'd prefer a React-specific Masonry library (no direct DOM manipulation), react-masonry-css handles layout updates automatically when components re-render. We'll use a state flag to trigger a re-render once Tweets are loaded:

import { useEffect, useState } from 'react';
import Masonry from 'react-masonry-css'; // Install via npm: npm install react-masonry-css

const TweetMasonryGrid = () => {
  const [areTweetsLoaded, setAreTweetsLoaded] = useState(false);

  useEffect(() => {
    // Load Twitter widget script
    const loadTwitterWidget = () => {
      if (document.getElementById('twitter-wjs')) return;
      const script = document.createElement('script');
      script.id = 'twitter-wjs';
      script.src = 'https://platform.twitter.com/widgets.js';
      script.async = true;
      document.body.appendChild(script);
    };

    loadTwitterWidget();

    // Listen for Tweets loaded event
    window.twttr?.ready((twttr) => {
      const handleTweetsLoaded = () => setAreTweetsLoaded(true);
      twttr.events.bind('loaded', handleTweetsLoaded);

      return () => twttr.events.unbind('loaded', handleTweetsLoaded);
    });

    const twttrCheckInterval = setInterval(() => {
      if (window.twttr) clearInterval(twttrCheckInterval);
    }, 100);

    return () => clearInterval(twttrCheckInterval);
  }, []);

  // Define responsive breakpoints
  const breakpointColumns = {
    default: 3,
    1100: 2,
    700: 1
  };

  return (
    <Masonry
      breakpointCols={breakpointColumns}
      className="grid"
      columnClassName="grid-column"
    >
      {/* Your grid items */}
      <div className="grid-item">
        <blockquote className="twitter-tweet">
          <p lang="en" dir="ltr">Another example tweet!</p>
          &mdash; Example User (@ExampleUser) <a href="https://twitter.com/ExampleUser/status/0987654321">February 1, 2020</a>
        </blockquote>
      </div>
      {/* More items here */}
    </Masonry>
  );
};

export default TweetMasonryGrid;

Why This Works

  • No jQuery Dependency: We use React's native hooks/lifecycle to manage script loading and event listeners, keeping everything in sync with React's component lifecycle.
  • Proper Cleanup: We unbind Twitter events and destroy Masonry instances when the component unmounts, preventing memory leaks.
  • Timing: The Twitter loaded event ensures we only initialize Masonry after all Tweets are rendered, so the layout uses the correct dimensions for each grid item.

内容的提问来源于stack exchange,提问作者Gaurav

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.27 07:35:13