¿Hay alguna manera de cambiar dinámicamente los colores en el <IconTint /> de la biblioteca react-icon-tint tint? Necesito que se cambie el color en el cambio de estado isActive , pero parece que no funciona como esperaba porque usa un elemento de canvas debajo del capó.
También traté de volver a representar todo el elemento en el cambio isActive así
{ isActive ? ( <IconTint src={getCustomIcon()} color={icon} /> ) : ( <IconTint src={getCustomIcon()} color={iconOnBackground} /> ); }Pero tampoco funcionó.
He mirado el código fuente, porque es un componente memorizado, no se vuelve a renderizar en el padre y porque dentro del useEffect que se usa dentro del componente, las dependencias como el color y la imagen src no están incluidas, no se vuelve a renderizar en cambio de prop, obviamente es un error o un comportamiento no deseado. No sé por qué tu forma de hacerlo no funciona, ¡porque esos dos componentes de IconTint son dos componentes diferentes!. pero puedes hacerlo de esta manera:
{isActive && <IconTint src={getCustomIcon()} color='#0000ff' />} {!isActive && <IconTint src={getCustomIcon()} color='#b43285' />}No creo que esto sea eficaz, el código fuente es muy simple, por lo que puede implementar IconTint dentro de su proyecto y simplemente agregar dependencias dentro de la matriz de dependencias useEffect. Aquí proporcioné una versión modificada.
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);ahora puedes usar esta versión modificada así:
<IconTint src={getCustomIcon()} color={isActive ? '#0000ff' : "#b43285"}/>