javascript - Rendering Duplication React.js - Stack Overflow

admin2025-04-17  1

I’m encountering an issue in my React project where a button is being rendered twice, but only the bottom button works.

If anyone has any suggestions or has seen this before, I’d appreciate your help!

import React, { useState, useEffect, useRef } from 'react';

const PixelatedImage = ({ imageUrl }) => {
  const [pixelatedSections, setPixelatedSections] = useState([true, true, true, true]); // All sections pixelated initially
  const canvasRef = useRef(null);

  useEffect(() => {
    if (!imageUrl) return; // Wait for image to load

    const canvas = canvasRef.current;
    const context = canvas.getContext("2d");
    const img = new Image();
    img.src = imageUrl;

    img.onload = () => {
      const width = img.width;
      const height = img.height;

      // Set canvas size to image size
      canvas.width = width;
      canvas.height = height;

      const pixelateSection = (left, top, sectionWidth, sectionHeight, pixelSize = 10) => {
        const offscreenCanvas = document.createElement("canvas");
        const offscreenContext = offscreenCanvas.getContext("2d");
        offscreenCanvas.width = sectionWidth;
        offscreenCanvas.height = sectionHeight;

        offscreenContext.drawImage(canvas, left, top, sectionWidth, sectionHeight, 0, 0, sectionWidth, sectionHeight);

        offscreenContext.imageSmoothingEnabled = false;
        offscreenContext.drawImage(offscreenCanvas, 0, 0, sectionWidth / pixelSize, sectionHeight / pixelSize);
        offscreenContext.drawImage(
          offscreenCanvas,
          0,
          0,
          sectionWidth / pixelSize,
          sectionHeight / pixelSize,
          0,
          0,
          sectionWidth,
          sectionHeight
        );

        context.drawImage(offscreenCanvas, left, top);
      };

      const unpixelateSection = (left, top, sectionWidth, sectionHeight) => {
        context.drawImage(img, left, top, sectionWidth, sectionHeight, left, top, sectionWidth, sectionHeight);
      };

      const drawCanvas = () => {
        context.clearRect(0, 0, canvas.width, canvas.height);
        context.drawImage(img, 0, 0, width, height);

        if (pixelatedSections[0]) pixelateSection(0, 0, width / 2, height / 2);
        if (pixelatedSections[1]) pixelateSection(width / 2, 0, width / 2, height / 2);
        if (pixelatedSections[2]) pixelateSection(0, height / 2, width / 2, height / 2);
        if (pixelatedSections[3]) pixelateSection(width / 2, height / 2, width / 2, height / 2);
      };

      drawCanvas();
    };
  }, [imageUrl, pixelatedSections]); // Redraw whenever pixelatedSections changes

  const unpixelateNextSection = () => {
    const nextPixelatedSections = [...pixelatedSections];
    const nextIndex = nextPixelatedSections.indexOf(true);

    if (nextIndex !== -1) {
      nextPixelatedSections[nextIndex] = false; // Unpixelate the first pixelated section

      setPixelatedSections(nextPixelatedSections); // Update the state to trigger a re-render
    }
  };

  return (
    <div>
      <canvas ref={canvasRef}></canvas>
      {/* Handle button click with React's onClick */}
      <button onClick={unpixelateNextSection}>Unpixelate Next Section</button>
    </div>
  );
};

export default PixelatedImage;

I’ve been trying to fix it with no luck so far, and here’s what I’ve attempted:

Checked the component rendering logic to make sure it's only rendering one button. Used document.getElementById and manually added event listeners, but that caused the button to render twice. Removed id and used React’s onClick event handler, but the problem still persists.

I’m encountering an issue in my React project where a button is being rendered twice, but only the bottom button works.

If anyone has any suggestions or has seen this before, I’d appreciate your help!

import React, { useState, useEffect, useRef } from 'react';

const PixelatedImage = ({ imageUrl }) => {
  const [pixelatedSections, setPixelatedSections] = useState([true, true, true, true]); // All sections pixelated initially
  const canvasRef = useRef(null);

  useEffect(() => {
    if (!imageUrl) return; // Wait for image to load

    const canvas = canvasRef.current;
    const context = canvas.getContext("2d");
    const img = new Image();
    img.src = imageUrl;

    img.onload = () => {
      const width = img.width;
      const height = img.height;

      // Set canvas size to image size
      canvas.width = width;
      canvas.height = height;

      const pixelateSection = (left, top, sectionWidth, sectionHeight, pixelSize = 10) => {
        const offscreenCanvas = document.createElement("canvas");
        const offscreenContext = offscreenCanvas.getContext("2d");
        offscreenCanvas.width = sectionWidth;
        offscreenCanvas.height = sectionHeight;

        offscreenContext.drawImage(canvas, left, top, sectionWidth, sectionHeight, 0, 0, sectionWidth, sectionHeight);

        offscreenContext.imageSmoothingEnabled = false;
        offscreenContext.drawImage(offscreenCanvas, 0, 0, sectionWidth / pixelSize, sectionHeight / pixelSize);
        offscreenContext.drawImage(
          offscreenCanvas,
          0,
          0,
          sectionWidth / pixelSize,
          sectionHeight / pixelSize,
          0,
          0,
          sectionWidth,
          sectionHeight
        );

        context.drawImage(offscreenCanvas, left, top);
      };

      const unpixelateSection = (left, top, sectionWidth, sectionHeight) => {
        context.drawImage(img, left, top, sectionWidth, sectionHeight, left, top, sectionWidth, sectionHeight);
      };

      const drawCanvas = () => {
        context.clearRect(0, 0, canvas.width, canvas.height);
        context.drawImage(img, 0, 0, width, height);

        if (pixelatedSections[0]) pixelateSection(0, 0, width / 2, height / 2);
        if (pixelatedSections[1]) pixelateSection(width / 2, 0, width / 2, height / 2);
        if (pixelatedSections[2]) pixelateSection(0, height / 2, width / 2, height / 2);
        if (pixelatedSections[3]) pixelateSection(width / 2, height / 2, width / 2, height / 2);
      };

      drawCanvas();
    };
  }, [imageUrl, pixelatedSections]); // Redraw whenever pixelatedSections changes

  const unpixelateNextSection = () => {
    const nextPixelatedSections = [...pixelatedSections];
    const nextIndex = nextPixelatedSections.indexOf(true);

    if (nextIndex !== -1) {
      nextPixelatedSections[nextIndex] = false; // Unpixelate the first pixelated section

      setPixelatedSections(nextPixelatedSections); // Update the state to trigger a re-render
    }
  };

  return (
    <div>
      <canvas ref={canvasRef}></canvas>
      {/* Handle button click with React's onClick */}
      <button onClick={unpixelateNextSection}>Unpixelate Next Section</button>
    </div>
  );
};

export default PixelatedImage;

I’ve been trying to fix it with no luck so far, and here’s what I’ve attempted:

Checked the component rendering logic to make sure it's only rendering one button. Used document.getElementById and manually added event listeners, but that caused the button to render twice. Removed id and used React’s onClick event handler, but the problem still persists.

Share edited Jan 31 at 6:02 rozsazoltan 11.3k6 gold badges21 silver badges59 bronze badges asked Jan 31 at 0:41 Carlos SalameCarlos Salame 431 silver badge9 bronze badges 2
  • I copy pasted your code and it only rendered once (Vite + React 19). You sure it's not something from above? – Salehi Commented Jan 31 at 5:04
  • How does the answer you accepted relate? Structure mode’s double-rendering doesn’t put two components on the screen, it renders the same component twice. – Dave Newton Commented Jan 31 at 22:19
Add a comment  | 

1 Answer 1

Reset to default 2

If your project uses React 18 with StrictMode enabled, React will intentionally double-render components in development mode to detect side effects. Check if StrictMode is enabled in index.js or main.jsx

<React.StrictMode>
  <App />
</React.StrictMode>

Try disabling StrictMode and running the code.

Check this question for more info.

转载请注明原文地址:http://anycun.com/QandA/1744884745a88996.html