OverlayScrollbars icon indicating copy to clipboard operation
OverlayScrollbars copied to clipboard

Strange behavior with Nuxt.js

Open ExileofAranei opened this issue 5 years ago • 14 comments

Hello, thanks for this very nice plugin. I faced a very strange problem using it with server side rendering in Nuxt.js. I created layout with sidebar and by clicking a button i can change it's width. My main and sidebar's contents are wrapped with OverlayScrollbars-vue component. Once the width of sidebar is changed (by setting flag in store), the main content's native scrollbar becomes visible along with plugin. It's looks like

image

This problem only exists with server side rendering, with SPA mode everything is seems ok. I created a sandbox to reproduce this behavior. In my project sidebar's scrollbar also brakes, but i couldn't reproduce it here. Applying v-once directive to overlayscrollbar-vue component fix it, but i need reactivity in child nodes. Tested it in Chrome and Firefox.

https://codesandbox.io/s/elastic-cerf-nrtlh

To reproduce:

  1. Open codesandbox;
  2. Click 'toggle' button in sidebar

ExileofAranei avatar May 25 '20 11:05 ExileofAranei

Good day!

Thanks for the example, but on my side is working everything correctly inside your example. Please tell me which OS and browser (with version) you are using.

KingSora avatar May 25 '20 14:05 KingSora

Thanks for fast response.

OS Windows 10.0.18363 Build 18363 Browser: Chrome 81.0.4044.138 (Official Build) (64-bit)

I changed type of plugin's include and now (at least for me) its brakes every time. Open sandbox again, please.

ExileofAranei avatar May 25 '20 16:05 ExileofAranei

Alright, now it breaks on my side too.

It seems like part of the DOM classes are overwritten by the classes inside the components template which is defined here. This is just the "blueprint" and there are classes added depending on the browser and its feature support. Thats why the scrollbar gets visible, because the class which is responsible to hide it gets added during initialization.

I honestly don't know what is happening.

Edit: Ok, after a bit of testing, this is indeed happning because vue re-renders the OverlayScrollbarsComponent which is in the yellow content. Thats why the classes are reset. In the Component logic itself isn't anything defined which re-renders the component so I don't exactly know why thats happening.

KingSora avatar May 25 '20 18:05 KingSora

Well, thanks for taking a look at this. Will try to find some workaround. Seems like the problem is related to Nuxt and SSR mode, because with pure Vue plugin works as expected and never brakes with the exactly same layout.

ExileofAranei avatar May 25 '20 19:05 ExileofAranei

Please let the codesandbox example unchanged as I can experiment with it to fix the issue. I believe I can create a workaround for that.

KingSora avatar May 26 '20 09:05 KingSora

I created a GitHub repository for this because for some reason i couldn't fork my own codesandbox without getting strange errors.

git clone https://github.com/ExileofAranei/overlayscrollbars-nuxt-experiments.git npm install npm run dev

ExileofAranei avatar May 26 '20 10:05 ExileofAranei

Hello! Sooo... any news on this issue? I've faced the exact same problem while using this plugin with Nuxt. The only workaround I've found is to wrap plugin's tags in <client-only></client-only>, so it's seems to be related to Nuxt's SSR.

disjointed avatar Jul 16 '20 18:07 disjointed

@disjointed I'm trying to figuring it out.. but I got no answer yet: https://github.com/nuxt/nuxt.js/issues/7706

KingSora avatar Jul 16 '20 18:07 KingSora

I've just hit this same issue, went in circles for ages wondering what it was! Again only happens on SSR, and fixed by using client-only but then you lose the SSR part.

Seems that some of the initialisation that happens on the server during SSR is carried over to the client, (which has a different browser) and so invalidates some of the probed config. Looks to me like the Vue component needs to rerun some of the initial checks when it gets mounted again and hydrated on the client side.

tekpanda avatar Mar 03 '21 13:03 tekpanda

I did manage to get it working by hacking in a reinitialisation after mounting on the component using it:

<template>
    <overlay-scrollbars ref="scroll" class="h-100" :options="{ className: 'os-theme-light' }">
            etc...
    </overlay-scrollbars>
</template>

In script...

mounted() {
    this.$refs.scroll._osInstace.destroy();

    setTimeout(() => {
        this.$refs.scroll._osInstace = OverlayScrollbars(
            this.$refs.scroll.osTarget(),
            this.$refs.scroll.options || {},
            this.$refs.scroll.extensions
        );
    }, 0);
}

tekpanda avatar Mar 03 '21 13:03 tekpanda

@tekpanda maybe better to use nextTick against setTimeout?

Alex-Sokolov avatar Mar 04 '21 09:03 Alex-Sokolov

@Alex-Sokolov Yes quite, my thought too, this was just a quick hack! Having looked at the code for the Vue component, the initialisation of the overlayscrollbars happens in the mounted hook which only runs client-side already, so I wonder if in fact all it needs to a wrap around next tick or similar in mounted?

tekpanda avatar Mar 04 '21 09:03 tekpanda

setTimeout doesn't guarantee that template will be updated, but nextTick recommended for using in that cases

Alex-Sokolov avatar Mar 05 '21 08:03 Alex-Sokolov

Another quick hack is to give the component a key to let it rerender on mounted:

<overlay-scrollbars :key="scroll" :options="{ scrollbars: { autoHide: 'scroll' } }"> CODE HERE </overlay-scrollbars>

mounted() { this.$nextTick(() => { this.scroll++; }); }

graphicfox avatar Aug 01 '21 17:08 graphicfox

This should be hopefully fixed with v2 and with it the newest version of overlayscrollbars-vue (v0.4.0)

KingSora avatar Nov 12 '22 12:11 KingSora