Bird
Raised Fist0
Vueframework~10 mins

Custom refs with customRef in Vue - Interactive Code Practice

Choose your learning style10 modes available
Practice - 5 Tasks
Answer the questions below
1fill in blank
easy

Complete the code to import the function needed to create a custom ref in Vue.

Vue
import { [1] } from 'vue';
Drag options to blanks, or click blank then click option'
AcustomRef
Bref
Creactive
Dcomputed
Attempts:
3 left
💡 Hint
Common Mistakes
Using 'ref' instead of 'customRef' for creating custom refs.
Importing 'reactive' or 'computed' which are different APIs.
2fill in blank
medium

Complete the code to define a custom ref that debounces updates by 300ms.

Vue
const debounced = customRef((track, trigger) => {
  let timeout;
  return {
    get() {
      [1]();
      return value;
    },
    set(newValue) {
      clearTimeout(timeout);
      timeout = setTimeout(() => {
        value = newValue;
        trigger();
      }, 300);
    }
  };
});
Drag options to blanks, or click blank then click option'
Atrack
Btrigger
CclearTimeout
DsetTimeout
Attempts:
3 left
💡 Hint
Common Mistakes
Calling 'trigger()' inside get instead of 'track()'.
Not calling any function inside get, so reactivity breaks.
3fill in blank
hard

Fix the error in the custom ref setter to correctly update the value and trigger reactivity.

Vue
set(newValue) {
  clearTimeout(timeout);
  timeout = setTimeout(() => {
    [1] = newValue;
    trigger();
  }, 300);
}
Drag options to blanks, or click blank then click option'
Atrigger
BnewValue
Cvalue
Dtimeout
Attempts:
3 left
💡 Hint
Common Mistakes
Assigning to 'newValue' which is the parameter, not the internal variable.
Calling 'trigger()' before updating the value.
4fill in blank
hard

Fill both blanks to create a custom ref that logs when it is read and written.

Vue
const loggerRef = customRef(([1], [2]) => {
  let value = '';
  return {
    get() {
      console.log('Value read');
      [1]();
      return value;
    },
    set(newValue) {
      console.log('Value written:', newValue);
      value = newValue;
      [2]();
    }
  };
});
Drag options to blanks, or click blank then click option'
Atrack
Btrigger
Cvalue
DnewValue
Attempts:
3 left
💡 Hint
Common Mistakes
Swapping the order of track and trigger.
Using variable names instead of functions for tracking and triggering.
5fill in blank
hard

Fill all three blanks to create a custom ref that only triggers updates if the new value is different.

Vue
const stableRef = customRef(([1], [2]) => {
  let value = null;
  return {
    get() {
      [1]();
      return value;
    },
    set(newValue) {
      if (newValue !== value) {
        value = newValue;
        [2]();
      }
    }
  };
});
Drag options to blanks, or click blank then click option'
Atrack
Btrigger
Cvalue
DnewValue
Attempts:
3 left
💡 Hint
Common Mistakes
Triggering updates even when the value is unchanged.
Not calling track in get, breaking reactivity.

Practice

(1/5)
1. What is the main purpose of using customRef in Vue?
easy
A. To create reactive references with custom get and set behavior
B. To define a component's template
C. To register global components
D. To handle lifecycle hooks automatically

Solution

  1. Step 1: Understand what customRef does

    customRef allows you to create reactive references where you control how the value is read and written.
  2. Step 2: Compare with other options

    Options A, C, and D relate to other Vue features, not customRef.
  3. Final Answer:

    To create reactive references with custom get and set behavior -> Option A
  4. Quick Check:

    customRef = custom reactive behavior [OK]
Hint: Remember: customRef customizes reactive get/set [OK]
Common Mistakes:
  • Confusing customRef with component registration
  • Thinking customRef manages lifecycle hooks
  • Assuming customRef defines templates
2. Which of the following is the correct way to import customRef in a Vue 3 component?
easy
A. import { CustomRef } from 'vue';
B. import customRef from 'vue';
C. import { customRef } from 'vue';
D. import * as customRef from 'vue';

Solution

  1. Step 1: Recall Vue 3 import syntax

    Vue exports customRef as a named export, so it must be imported with curly braces.
  2. Step 2: Check each option

    import { customRef } from 'vue'; uses correct named import syntax. import customRef from 'vue'; tries default import which is incorrect. import { CustomRef } from 'vue'; uses wrong capitalization. import * as customRef from 'vue'; imports everything as an object, which is not typical for this usage.
  3. Final Answer:

    import { customRef } from 'vue'; -> Option C
  4. Quick Check:

    Named import uses curly braces [OK]
Hint: Use curly braces for named imports like customRef [OK]
Common Mistakes:
  • Using default import instead of named import
  • Wrong capitalization of customRef
  • Importing everything instead of named import
3. Given the following code, what will be logged when myRef.value = 10 is called?
import { customRef } from 'vue';

const myRef = customRef((track, trigger) => {
  let value = 0;
  return {
    get() {
      track();
      return value;
    },
    set(newValue) {
      if (newValue !== value) {
        value = newValue;
        trigger();
        console.log('Value updated');
      }
    }
  };
});

myRef.value = 10;
medium
A. Value updated
B. No output
C. Error: track is not defined
D. Value updated twice

Solution

  1. Step 1: Understand the set function behavior

    The set function checks if the new value differs from the current one. Since 10 !== 0, it updates value, triggers reactivity, and logs 'Value updated'.
  2. Step 2: Confirm no repeated logs or errors

    There is no repeated assignment or error in the code, so only one log occurs.
  3. Final Answer:

    Value updated -> Option A
  4. Quick Check:

    Set logs once on value change [OK]
Hint: Set logs only when value changes [OK]
Common Mistakes:
  • Expecting no output because of track confusion
  • Thinking trigger causes multiple logs
  • Assuming error due to track usage
4. Identify the error in this customRef implementation:
import { customRef } from 'vue';

const myRef = customRef((track, trigger) => {
  let value = 0;
  return {
    get() {
      return value;
    },
    set(newValue) {
      value = newValue;
      trigger();
    }
  };
});
medium
A. customRef cannot be used with arrow functions
B. Missing call to trigger() inside get()
C. Value should be declared with ref()
D. Missing call to track() inside get()

Solution

  1. Step 1: Check get() method for reactivity tracking

    The get() method must call track() to register dependencies. Here, it returns value without calling track(), so reactivity won't work properly.
  2. Step 2: Verify other parts

    Trigger is correctly called in set(). Value does not need to be a ref inside customRef. Arrow functions are allowed.
  3. Final Answer:

    Missing call to track() inside get() -> Option D
  4. Quick Check:

    track() needed in get() for reactivity [OK]
Hint: Always call track() inside get() [OK]
Common Mistakes:
  • Forgetting to call track() in get()
  • Thinking trigger() is needed in get()
  • Assuming value must be a ref inside customRef
5. You want to create a customRef that debounces updates by 300ms before triggering reactivity. Which code snippet correctly implements this behavior?
hard
A. const debouncedRef = customRef((track, trigger) => { let value; return { get() { track(); return value; }, set(newValue) { value = newValue; trigger(); } }; });
B. const debouncedRef = customRef((track, trigger) => { let value; let timeout; return { get() { track(); return value; }, set(newValue) { clearTimeout(timeout); timeout = setTimeout(() => { value = newValue; trigger(); }, 300); } }; });
C. const debouncedRef = customRef((track, trigger) => { let value; let timeout; return { get() { return value; }, set(newValue) { clearTimeout(timeout); timeout = setTimeout(() => { value = newValue; trigger(); }, 300); } }; });
D. const debouncedRef = customRef((track, trigger) => { let value; let timeout; return { get() { track(); return value; }, set(newValue) { value = newValue; clearTimeout(timeout); timeout = setTimeout(() => { trigger(); }, 300); } }; });

Solution

  1. Step 1: Understand debounce logic in set()

    Debounce means delaying the update and trigger until 300ms after the last set call. The correct code clears previous timeout, sets new timeout to update value and trigger after 300ms.
  2. Step 2: Check get() calls track()

    The correct code calls track() in get() to register dependencies. Missing track() in get() breaks reactivity. The remaining options either lack track(), do not debounce properly, or have incorrect debouncing logic.
  3. Final Answer:

    Correctly implements debounced updates with track() in get() -> Option B
  4. Quick Check:

    Debounce needs clearTimeout + delayed trigger [OK]
Hint: Debounce by delaying trigger with setTimeout and clearTimeout [OK]
Common Mistakes:
  • Not calling track() inside get()
  • Triggering immediately without debounce
  • Setting value outside timeout causing immediate update
Recommended

Ready to prove it?

Pass the test and this pattern moves unknown strong while earning +1 Grip toward your certificate.

10 questions~5 mineasy hard