Tengo una aplicación PHP existente que administra productos. Cada producto puede tener múltiples imágenes. Actualmente, el proceso de agregar o eliminar imágenes se maneja a través del lado del servidor PHP y, por lo tanto, requiere una carga de página en cada acción.
Como esta es una gran aplicación existente, estoy buscando hacer mejoras en todo y una de ellas es reemplazar esta sección de agregar/eliminar imágenes con un componente de reacción.
Entonces, he hecho exactamente eso. Creé un componente llamado ImageManager y lo convertí en un div con una identificación.
editarProducto.html.twig
<div id="image-manager" data-js-images="{images: ['1.jpg', '2.jpg', '3.jpg']}"></div>aplicación.js
// Grab element & props const element = document.getElementById('image-manager'); const props = element.dataset; // Render it ReactDOM.render(<ImageManager {...props} />, element);Cosas simples hasta ahora. Aquí está mi componente... ImageManager.js
import React, {Fragment, useState, useEffect} from 'react'; const ImageManager = ({jsImages}) => { const [images, setImages] = useState([]); // When jsImages changes useEffect(() => { setImages(jsImages); }, [jsImages]); return ( <Fragment> <div className="row"> {images.map((img, idx) => { return ( <div key={idx} className="col-2"> <img src={img}/> <button type="button" className="btn btn-danger" onClick={() => { // Remove it const imagesCopy = [...images]; imagesCopy.splice(idx, 1); setImages(imagesCopy); }}>Remove</button> </div> ); })} </div> </Fragment> ); }; export default ImageManager;Todo esto funciona muy bien, sin embargo... el problema que tengo es que se agregan nuevas imágenes y se manejan fuera de este componente por algunos JS regulares que no reaccionan. Hay un botón en otro lugar fuera de la página que maneja la carga de la imagen y devuelve el nuevo nombre de archivo del servidor.
Entonces mi pregunta es, ¿cómo le hago saber a mi componente ImageManager que hay una nueva imagen? Parece que el componente no detecta el cambio del atributo "data-js-images". Supongo que esto solo se lee una vez y si se actualiza, no pasa nada.
Si vuelvo a renderizar el componente y simplemente lo combino en mi nueva imagen, luego lo paso al atributo "data-js-images", entonces funciona bien, pero siento que volver a renderizar un componente completo no es la forma "correcta" de ¿haciendo esto?
Para que quede claro, no hay un componente de nivel superior ni nada por el estilo. Solo hay un archivo app.js y un montón de HTML.
¡Cualquier ayuda sería muy apreciada! Gracias
El gancho useEffect no se usa aquí, porque solo renderizas el componente una vez y no cambias los accesorios. Debe observar el elemento html con el atributo de datos y, cuando cambie, debe actualizar los accesorios de los componentes.
Podrías usar el constructor MutationObserver con eso, por ejemplo
const observer = new MutationObserver((mutations, observer) => { // Do something when the element changes }); observer.observe(element, { attributes: true });No lo he probado yo mismo, pero debería funcionar. De lo contrario, eche un vistazo a este artículo.