babel-plugin-jsx icon indicating copy to clipboard operation
babel-plugin-jsx copied to clipboard

When JSX is used, v-slots cause child component does unnecessary rendering during parent component re-rendering

Open yuwu9145 opened this issue 1 year ago • 17 comments

Vue version

3.4.21

Link to minimal reproduction

https://github.com/yuwu9145/vue-jsx-slot-demo

Steps to reproduce

  1. Load and run the project
  2. Type something in the input to trigger parent App component render function
  3. Check console logs
  4. Then go to src/App.tsx and comment out line 20
  5. Type something again
  6. Check console logs again, see the different results

What is expected?

Only parent App component's onUpdated hook should be triggered, child Test component should not be re-rendered as nothing is changed to trigger child Test render function

What is actually happening?

Both parent App and child Test components are re-rendered

System Info

System:
    OS: macOS 14.2.1
    CPU: (8) arm64 Apple M1 Pro
    Memory: 114.45 MB / 16.00 GB
    Shell: 5.9 - /bin/zsh
  Binaries:
    Node: 18.19.0 - ~/.nvm/versions/node/v18.19.0/bin/node
    Yarn: 1.19.0 - ~/.nvm/versions/node/v18.19.0/bin/yarn
    npm: 10.2.3 - ~/.nvm/versions/node/v18.19.0/bin/npm
  Browsers:
    Chrome: 125.0.6422.141
    Firefox: 124.0.2
    Safari: 17.2.1
  npmPackages:
    vue: ^3.4.27 => 3.4.21

Any additional comments?

No response

yuwu9145 avatar May 31 '24 11:05 yuwu9145

Hi folks, Is there an expected timeline for resolving this issue? I am waiting eagerly for a fix here because it affects the linked rendering of VTreeview in Vuetify quite significantly. No intend to pressure - just curious as it would affect my planning in a work-around. Thank you!

uke5tar avatar Jun 12 '24 12:06 uke5tar

+1 same for me, same boat

TheInvoker avatar Jun 12 '24 15:06 TheInvoker

this is the last item I need updated to convert my project from vue2 to vue3, would love an ETA

angrymarker avatar Jul 30 '24 13:07 angrymarker

Is there an expected repair time? I think this has a great impact on performance

Zheng-Changfu avatar Aug 05 '24 03:08 Zheng-Changfu

Setting $stable to true in v-slots prevents updates for subcomponents,I'm looking at this issue:https://github.com/vuejs/babel-plugin-jsx/issues/525

Zheng-Changfu avatar Aug 05 '24 08:08 Zheng-Changfu

v-slots={{ $stable:true }}

Zheng-Changfu avatar Aug 05 '24 08:08 Zheng-Changfu

$stable:true resolves our performance issue, what's the official way of using it?

yuwu9145 avatar Aug 09 '24 04:08 yuwu9145

$stable:true解决了我们的性能问题,官方的使用方法是什么?

jsx 目前没有做这种编译处理, vue slot 有3种类型,stable、dynamic、forward,template 语法会在编译过程中根据上下文自动编译出插槽类型,从而在更新判断中做优化处理,而 jsx 没有做这种处理,所以会强制更新

vue 更新判断源码 vue slot types vue 目前没办法做到插槽的依赖收集

Zheng-Changfu avatar Aug 09 '24 06:08 Zheng-Changfu

$stable:true解决了我们的性能问题,官方的使用方法是什么?

jsx 目前没有做这种编译处理, vue slot 有3种类型,stable、dynamic、forward,template 语法会在编译过程中根据上下文自动编译出插槽类型,从而在更新判断中做优化处理,而 jsx 没有做这种处理,所以会强制更新

vue 更新判断源码 vue slot types vue 目前没办法做到插槽的依赖收集

stable 才会在更新过程中做优化,dynamic 会强制更新,forward 会根据运行时的行为决定

Zheng-Changfu avatar Aug 09 '24 06:08 Zheng-Changfu

Any updates ?

mxcabre avatar Sep 17 '24 23:09 mxcabre

I just use an additional type system. I can't think of a better way:

  type SlotType<A = any> = (...args: Array<A>) => VNode;

  type DefaultSlot = {
    default?: SlotType;
  };

 type PropsWithVSlots<S extends Record<string, SlotType>, P = unknown> = P & {
   vSlots?: S & {
     $stable?: boolean;
   };
 };

and

const Component = defineComponent<PropsWithVSlots<DefaultSlot, {}>, {}, '', SlotsType<DefaultSlot>>(
  (_, { slots }) =>
    () => <div>{slots.default?.()}</div>
 );

 <Component
    vSlots={{
       $stable: true,
       default: () => (<div>Content</div>),
     }}
  />

lowrider-fn avatar Jan 13 '25 12:01 lowrider-fn

Any chance we could push this forward?

yuwu9145 avatar Jan 17 '25 22:01 yuwu9145

Wondering if any progress will be made on this soon.

landynfrancis avatar Mar 19 '25 17:03 landynfrancis

Now the $stable flag will be automatically add for v-slot directive. https://github.com/vue-macros/vue-macros/pull/942

This is a vue-macros's feature that supports the v-slot directive in JSX, similar to its usage in Vue templates. However, for babel-plugin-jsx, the value of v-slots is an object, which makes it impossible to automatically determine whether to add the $stable flag.

zhiyuanzmj avatar Apr 06 '25 07:04 zhiyuanzmj

Is there a planned timeline for a new release with this fix included?

landynfrancis avatar May 15 '25 13:05 landynfrancis

估计不会更新

---- Replied Message ---- | From | @.> | | Date | 05/15/2025 21:21 | | To | vuejs/babel-plugin-jsx @.> | | Cc | Zheng-Changfu @.>, Comment @.> | | Subject | Re: [vuejs/babel-plugin-jsx] When JSX is used, v-slots cause child component does unnecessary rendering during parent component re-rendering (Issue #712) | landynfrancis left a comment (vuejs/babel-plugin-jsx#712)

Is there a planned timeline for a new release with this fix included?

— Reply to this email directly, view it on GitHub, or unsubscribe. You are receiving this because you commented.Message ID: @.***>

Zheng-Changfu avatar May 16 '25 05:05 Zheng-Changfu

Can we have some movement on this please? What's required to get it over the hill?

johnleider avatar May 16 '25 17:05 johnleider