Empresas
Empleos
  • Sobre nosotros
  • Soluciones
    • Publicación de vacantes
      Publica tu vacante y recibe candidatos calificados en 48h.
    • Evaluación de candidatos
      500+ pruebas técnicas y psicológicas, más anti-fraude.
    • Headhunting
      Búsqueda ejecutiva a la medida de principio a fin.
    • Nómina + EOR
      Dispersión de nómina y EOR en más de 15 países de LATAM.
  • Precios
  • Empleos

0

264
Vistas
How to fire Watcher, when newValue is the same String?

I'm inserting base64 images into an editor by assigning their base64 string to reactive object state.image and pointing a watcher at it. Problem is that when I want to insert the same image twice, the watcher doesn't fire.

watcher:

const renderImage = (editor) => {
    const unwatch = watch(() => state.image, () => {
        console.log('watcher fires!')
        editor.chain().focus().setImage({ src: state.image }).run()
        unwatch()
        state.image = null
    })
}

As you can see I'm trying to kill the watcher with unwatch() and in addition set state.image = null but it still doesn't fire when the same image is loaded.

The @click event is triggered in this element:

<button  @click="$refs.image.click(); renderImage(editor)"></button>

<input type="file" ref="image" style="display: none" @change="getImageUrl">

and the dataUrl of the image is created in getImageUrl:

const getImageUrl = (event) => {
    const files = event.target.files;
    if (!files.length)
        return;
    const reader = new FileReader();
    reader.onload = (event) => {
        state.image = event.target.result;
    };
    reader.readAsDataURL(files[0]);
}

Both elements seem to work as desired.

How do I make the watcher fire?

about 4 years ago · Juan Pablo Isaza
1 Respuestas
Responde la pregunta

0

The question assumes the watch callback isn't firing, but in this case, it's actually the <input> that isn't firing its event.

The <input> only fires the change/input event when its value actually changes. When selecting the same file, the value hasn't changed, and thus no change-event occurs to call the getImageUrl() handler, which would've triggered the watch when the file gets loaded.

To resolve the issue, reset the <input>'s value after copying the selected file's path:

⋮
const image = ref() // template ref on input

const getImageUrl = (event) => {
    const files = event.target.files;
    if (!files.length)
        return;

    const fileToRead = files[0]; // 1️⃣ copy input's value
    image.value.value = null;    // 2️⃣ and reset the input
  
    const reader = new FileReader();
    reader.onload = (event) => {
        state.image = event.target.result;
    };
    reader.readAsDataURL(fileToRead);
}

demo 1

Minor refactoring

renderImage() is actually just using watch to essentially create an async callback for FileReader's load event. It seems this could be simplified by moving the image rendering code into that load-event handler directly:

const getImageUrl = (event) => {
    const files = event.target.files;
    if (!files.length)
        return;

    const fileToRead = files[0];
    image.value.value = null;

    const reader = new FileReader();
    reader.onload = (event) => {
        // 👇 render image
        editor.chain().focus().setImage({ src: event.target.result }).run();
    };
    reader.onerror = reject;
    reader.readAsDataURL(fileToRead);
}

Then you could remove renderImage():

<!-- <button @click="$refs.image.click(); renderImage(editor)"></button> --> <!-- no longer needed -->

<button @click="$refs.image.click()"></button>

...and also state.image:

const state = reactive({
  // image: '' // no longer needed
})

demo 2

about 4 years ago · Juan Pablo Isaza Denunciar
Responde la pregunta
Encuentra empleos remotos

¡Descubre la nueva forma de encontrar empleo!

Top de empleos
Top categorías de empleo
Empresas
Publicar vacante Precios Comercial
Legal
Términos y condiciones Política de privacidad
© 2026 PeakU Inc. All Rights Reserved.
Andres GPT
Recomiéndame algunas ofertas
Necesito ayuda