diff --git a/packages/runtime-core/__tests__/rendererTemplateRef.spec.ts b/packages/runtime-core/__tests__/rendererTemplateRef.spec.ts index 9f26bf9bdf8..ae6c605dd07 100644 --- a/packages/runtime-core/__tests__/rendererTemplateRef.spec.ts +++ b/packages/runtime-core/__tests__/rendererTemplateRef.spec.ts @@ -539,4 +539,42 @@ describe('api: template refs', () => { '
[object Object],[object Object]
', ) }) + + // #10655 warn if reactive array used as a ref inside v-for + test('string ref pointing to reactive() in v-for, should warn that it will not work in prod for scripSetup', () => { + const list = ref([1, 2, 3]) + const reactiveRef = reactive([]) + const App = { + setup() { + return { + reactiveRef, + __isScriptSetup: true, + } + }, + render() { + return h('div', null, [ + h( + 'ul', + list.value.map(i => + h( + 'li', + { + ref: 'reactiveRef', + ref_for: true, + }, + i, + ), + ), + ), + ]) + }, + } + const root = nodeOps.createElement('div') + render(h(App), root) + + expect( + 'In production mode ref array will not be filled. ' + + 'Use ref() instead. Ref name: reactiveRef', + ).toHaveBeenWarned() + }) }) diff --git a/packages/runtime-core/src/rendererTemplateRef.ts b/packages/runtime-core/src/rendererTemplateRef.ts index b652edeac4c..7ad9a4cde73 100644 --- a/packages/runtime-core/src/rendererTemplateRef.ts +++ b/packages/runtime-core/src/rendererTemplateRef.ts @@ -103,6 +103,20 @@ export function setRef( if (rawRef.k) refs[rawRef.k] = ref.value } } else if (!existing.includes(refValue)) { + // #10655 warn if not ref() array used as a string ref + const wrongRefType = + __DEV__ && + _isString && + hasOwn(owner.devtoolsRawSetupState, ref) && + !isRef(owner.devtoolsRawSetupState[ref]) && + hasOwn(setupState, '__isScriptSetup') + if (wrongRefType) { + warn( + 'In production mode ref array will not be filled. ' + + 'Use ref() instead. Ref name: ' + + ref, + ) + } existing.push(refValue) } }