jack.py
jack.py

Reputation: 442

Create computed property dependent on variables within onMounted() lifecycle hook

I have a component that needs to calculate some values using the DOM, and so I have the onMounted() lifecycle hook. In onMounted() I calculate some values (technically, they're computed properties) dependent on DOM elements.

I then use the values found in another computed property, leftOffset. I need to use leftOffset in template (it changes some CSS, not really relevant).

Below is my setup():

setup() {
    let showContent = ref(false);
    
    let windowWidth = ref(null);
    let contentHider = ref(null);

    let contentHiderXPos ;
    let contentHiderWidth ;
    let leftWidth;

    onMounted(() => {
        // The DOM element will be assigned to the ref after initial render
        windowWidth = ref(window.innerWidth);

        contentHiderXPos = computed(() => contentHider.value.getBoundingClientRect().left);
        contentHiderWidth = computed(() => contentHider.value.getBoundingClientRect().width);
        leftWidth = computed(() => contentHiderXPos.value + contentHiderWidth.value);
    });

    let leftOffset = computed(() => {
        return -(windowWidth.value - leftWidth.value)
    });

    return {
        contentHider,
        leftOffset,
    }

contentHider references a the DOM element of one of the divs defined in template.

My problem that leftOffest.value is undefined, because it tries to access windowWidth.value and leftWidth.value, which are also undefined. I've also tried putting leftOffset inside onMounted(), but then I can't access it from template (it's undefined).

How can I re-structure my code so that leftOffset can both be accessed from template and can also access the values found in onMounted()?

I've searched online, but couldn't find anything specific to the composition API.

Upvotes: 0

Views: 1174

Answers (1)

Chin. Udara
Chin. Udara

Reputation: 744

Your usage of the ref is wrong. Follow the comments in the below snippet.

Also this is assuming that you do not want the window.innerwidth to be reactive.

// dont create another ref => you are trying to assign a new object here, thus breaking the reactivity
// windowWidth = ref(window.innerWidth);
// do this instead
windowWidth.value = window.innerWidth

If you want the innerWidth to be reactive, you have to use the native event listener like this;

const windowWidth = ref(window.innerWidth)
onMounted(() => {
    window.addEventListener('resize', () => {windowWidth.value = window.innerWidth} )
})
onUnmounted(() => {
    window.removeEventListener('resize', () => {windowWidth.value = window.innerWidth})
}) 

Upvotes: 1

Related Questions