Business
Jobs
  • About Us
  • Solutions
    • Job Postings
      Post your job and receive qualified candidates in 48h.
    • Candidate Assessments
      500+ technical and psychological tests, plus anti-fraud.
    • Headhunting
      Tailor-made executive search from start to finish.
    • Payroll + EOR
      Payroll dispersal and EOR across 15+ LATAM countries.
  • Pricing
  • Jobs

0

142
Views
React IconTint (canvas) change color dynamically

Is there a way to change colors on <IconTint /> element from react-icon-tint library dynamically? I need the color to be changed on isActive state change but looks like it's not working as I expected because it uses canvas element under the hood.

I also tried to rerender the whole element on isActive change like that

{
  isActive ? (
    <IconTint src={getCustomIcon()} color={icon} />
  ) : (
    <IconTint src={getCustomIcon()} color={iconOnBackground} />
  );
}

But it also did not work.

about 4 years ago · Juan Pablo Isaza
1 answers
Answer question

0

I have looked at the source code, because it is a memoized component, it does not rerender on parent rerender, and because inside the useEffect that is used inside the component, dependencies like color and image src is not included, it does not rerender on prop change, obviously it is a bug, or an unwanted behaviour. I don't know why your way of doing it does not work, because those two IconTint components are two different components!. but you can do it this way:

 {isActive && <IconTint src={getCustomIcon()} color='#0000ff' />}
 {!isActive && <IconTint src={getCustomIcon()} color='#b43285' />}

I don't think this is performant, the source code is so simple, so you can implement IconTint inside your project and just add dependencies inside useEffect dependency array. Here I provided modified version.

import React, { memo, useEffect, useRef, useState } from "react";
import PropTypes from "prop-types";

const IconTint = ({ fallback = <span />, src, color, maxWidth, maxHeight }) => {
  const canvasRef = useRef(null);
  const [size, setSize] = useState({});

  const _scaleImage = (srcWidth, srcHeight, maxWidth, maxHeight) => {
    if (maxWidth && maxHeight) {
      const ratio = Math.min(maxWidth / srcWidth, maxHeight / srcHeight);
      return { width: srcWidth * ratio, height: srcHeight * ratio };
    }
    if ((maxWidth && !maxHeight) || (!maxWidth && maxHeight)) {
      throw new Error(
        "If you are going to provide width, make sure to provide height as well"
      );
    }
    return { width: srcWidth, height: srcHeight };
  };

  useEffect(() => {
    const canvas = canvasRef.current;
    // eslint-disable-next-line no-undef
    const pic = new Image();
    pic.src = src;
    const tintCanvas = document.createElement("canvas");
    const tintCtx = tintCanvas.getContext("2d");
    const ctx = canvas.getContext("2d");
    pic.onload = () => {
      const result = _scaleImage(pic.width, pic.height, maxWidth, maxHeight);
      setSize(result);
      tintCanvas.width = result.width;
      tintCanvas.height = result.height;
      tintCtx.fillStyle = color;
      tintCtx.fillRect(0, 0, result.width, result.height);
      tintCtx.globalCompositeOperation = "destination-atop";
      tintCtx.drawImage(pic, 0, 0, result.width, result.height);
      ctx.globalAlpha = 1;
      ctx.drawImage(tintCanvas, 0, 0, result.width, result.height);
    };
  }, [src,color,maxHeight,maxWidth]);

  if (
    typeof window !== "undefined" &&
    window.document &&
    window.document.createElement
  ) {
    return <canvas width={size.width} height={size.height} ref={canvasRef} />;
  }
  return fallback;
};

IconTint.propTypes = {
  src: PropTypes.string.isRequired,
  color: PropTypes.string.isRequired,
  fallback: PropTypes.node,
  maxWidth: PropTypes.number,
  maxHeight: PropTypes.number
};

export default memo(IconTint);

now you can use this modified version like this:

<IconTint src={getCustomIcon()} color={isActive ? '#0000ff' : "#b43285"}/>
about 4 years ago · Juan Pablo Isaza Report
Answer question
Find remote jobs

Discover the new way to find a job!

Top jobs
Top job categories
Business
Post vacancy Pricing Sales
Legal
Terms and conditions Privacy policy
© 2026 PeakU Inc. All Rights Reserved.
Andres GPT
Show me some job opportunities
There's an error!