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

263
Views
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 answers
Answer question

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 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!