-
-
Notifications
You must be signed in to change notification settings - Fork 8.5k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
when use custom v-model (with <script setup> style),it goes well in dev env,but may occur error:modelValue is undefined in production env #5584
Comments
Is there a more realistic scenario in which this happens? In your example, you use This is likely the root cause of the error: The compiler so far doesn't take this possibility into account as your can't v-model a prop directly.. |
<input :value="modelValue" @input="$emit('update:modelValue', $event.target.value)"/> |
that doesn't create any problems. |
that is the working alternative. a prop should technically not be used in v-model since its read-only, but the compiled output can still be more correct. also
<script setup>
import {toRef} from "vue"
let props = defineProps(['someProp'])
// uncomment line will prevent error.
//const someProp = toRef(props,'someProp')
</script>
<template>
<input v-model="someProp" />
</template> compiled output return (_ctx, _cache) => {
return _withDirectives((_openBlock(), _createElementBlock("input", {
"onUpdate:modelValue": _cache[0] || (_cache[0] = $event => (_isRef(someProp) ? (someProp).value = $event : null))
}, null, 512 /* NEED_PATCH */)), [
[_vModelText, __props.someProp]
])
}
} |
thank you all, I will modify my codes, best wishes for you two,god kiss you |
I run into this issue when deploying in production yesterday here is some example : Setup version @LinusBorg I understand v-model="modelValue" is not something you want, but it should throw a warning in dev at least, having an inconsistent behavior between dev and production is dangerous. For this kind of component having |
I didn't actually close this, the author did and j missed that. |
I feel it's a bug. } else {
// v-model used on a potentially ref binding in <script setup> inline mode.
// the assignment needs to check whether the binding is actually a ref.
const altAssignment =
bindingType === BindingTypes.SETUP_LET ? `${rawExp} = $event` : `null`
assignmentExp = createCompoundExpression([
`${eventArg} => (${context.helperString(IS_REF)}(${rawExp}) ? (`,
createSimpleExpression(rawExp, false, exp.loc),
`).value = $event : ${altAssignment})`
])
} |
I also meet this problem, I think this error should be output in dev env. |
also getting this in prod |
Is this a big issue? i see it was issued 28 days ago now @yyx990803 . Thanks! |
I have created a playground for this problem: Link If click on the
Whereas in the Expecting a fix to this problem, since its critical for making reusable components. Any suggestions for alternate approach is also appreciated 🙏 Attaching screenshots: PROD ModeDEV Mode |
This needs to be fixed as soon as possible. I wasted more than 2 hours because of this no-sense problem. Working dev but not in production without explanation is frustrating. |
This bug is very annoying but there's a workaround: if (import.meta.env.PROD) { var modelValue = toRef(props, 'modelValue') } it's a ugly but it works, the only thing you need to adapt is the production check (import.meta.env.PROD is a Vite variable). |
This approach is even documented in docs, but it doesn't work in production: |
@preeteshjain Your approach is not mutating an object or array prop, and you approach is still mutating a prop, so that's not what the docs recommend. |
I had a similar issue recently, the workaround I went with was creating a computed with a get and set. Passing the get to model and having the set emit the update. const value = computed({
get() {
return props.modelValue;
},
set(value) {
emit("update:modelValue", value);
},
}); <input v-model="value" /> |
To be honest, I still do not understand this problem. This is my code, let's see if you could see what's happening here, at least to understand the issue. Partent component
Child component
As I said before, I have other form components created the exactly same way and they are all working fine. If you need an example of them, please let me know. If you will, you can have a look in the console where the error happens in production: Thanks. |
To everyone facing this issue, the only way to fix this problem is to make sure (double check carefully) that you are not modifying your props from child component. We are now modifying the data from the parent only and passing it down as a prop to the child component and it is working in production environment. Here's how I have fixed the problem in the example I shared above:
Note that each scenario is different and the solution above is just an example. Hope the solution gives some insipiration for you guys to fix your problem. You guys will have to figure out your own approach making sure you don't change Parent's props from Child component. That being said, I think the only problem with Vue 3 currently is that it isn't notifying about this problem in |
Isn't it the main purpose of 2 way data binding? The availability to change the value of a property either in parent or child component? |
@preeteshjain There is two issues :
|
Hi, It happens to me with a getter/setter computed. In the following example, Works in dev build, but not in prod build: <template>
<button @click="thingId = 0">Select first thing</button>
<button @click="thingId = 1">Select second thing</button>
<SomeComponent v-model="thing" />
</template>
<script>
export default {
data: () => ({
things: [{ id: 0, name: "something" }, { id: 1, name: "something else" }],
thingId: 0
}),
computed: {
thing: {
get: ({ things, thingId }) => things.find(({ id }) => id === thingId),
set(thing) {
Object.assign(this.thing, thing);
}
}
}
};
</script> Result: console error similar to others about Now let's replace the computed setter with a method, while keeping exactly the same code, but this time it will works in both Dev en Prod build: <template>
<button @click="thingId = 0">Select first thing</button>
<button @click="thingId = 1">Select second thing</button>
<SomeComponent :modelValue="thing" @update:modelValue="handleThingUpdate" />
</template>
<script>
export default {
data: () => ({
things: [{ id: 0, name: "something" }, { id: 1, name: "something else" }],
thingId: 0
}),
computed: {
thing: ({ things, thingId }) => things.find(({ id }) => id === thingId)
},
methods: {
handleThingUpdate(thing) {
Object.assign(this.thing, thing);
}
}
};
</script> @LinusBorg since in this example there is no prop at all in the component, I guess your arg about "mutating a prop" isn't applicable here, right? In addition, that code isn't mutating the computed value itself because an |
Deleting script setup solved my issue, it's now works on both DEV and PROD environment, thanks! |
Just to clarify, there is "Options API" and "Composition API", none of them are "legacy" or "old style". In addition, there is still one thing which can't be done in composition API at all: disabling Keeping that in mind, we already an answer to the question:
We also have official advises here:
I guess this is enough, right? 😉 So now, the real question is: can we hope an official statement, or even better a fix, to the consistency issue between dev/prod build which is encountered by many dev in various scenario? @LinusBorg ? 🥺 |
@M1CK431 Hi. Yes, we have an inconsistencies here. The one originally reported in this issue is an edge case as really, it's an invalid use of v-model on a prop. As such, it does not have high priority. The one you now reported sounds similar, yet would be a separate issue as the original one is related to a compiler issue with TBH, I'm not even sure what error to look for as you never mentioned how it does not work in prod. Could you have a look and maybe adjust my attempt to reproduce the issue you are seeing? if it only happens in a real project build, please provide a small repro in a separate issue. |
Thanks for this quick reply and confirmation @LinusBorg 🙏
=> I agree, my linter is reporting me this kind of mistake (
=> You are perfectly right, I'm sorry and will open a dedicated issue.
=> mmmm ok, I was thinking it was clear enough when I was explaining:
But now I figure it was not so clear in fact... 🤭 To be more precise, the object property isn't updated in the parent component when the child component emit the The playground you provide looks good and, as I was explaining, is similar to the behavior I have in build dev (aka everything works as expected). The issue happens only with prod build.
=> Unfortunately, the project I'm working on is closed source so I can't directly provide the code. However, I will try to provide a repo, with a source code producing a working dev build but a not working prod build (and both will be in the repo too). Again, thanks a lot for the time you take to reply and try to reproduce the issue 😘 |
@LinusBorg I just open a dedicated issue with a reproduction repo here: #6677 |
Well, the docs states:
And then
So this states that yes, you can use it but it's advised to choose one or the other unless you know what you're doing. For a newbie this is quite confusing. But I agree that, reading this with the proper mindset fully covers the point.
Yes. This is the real problem as this is a bug in compilation/transpiling related to that type of setup. |
@xcash take a look at #6677, that type of setup is unsupported in fact. Dev have to choose one single API per component. Anyway we now have a clear statement and it's already a good point 👍 |
This is the best |
this issue |
Thanks, it really helps me. |
I have solved this problem like this. <template>
<div>
<input
v-model="val"
@change="onChange" />
</div>
</template>
<script setup lang="ts">
import { ref } from 'vue'
const props = defineProps({value: {},})
const val = ref(props.value)
const emit = defineEmits<{(event: 'onChange', value: any): void}>()
const onChange = () => {
emit('onChange', val.value)
}
</script> |
This problem is happening to me too. I jumped into the source code and found that modifying the produced code like this fixes the problem: PRODUCED CODE FIXED PRODUCED CODE So there's a bug when adding
|
Found another solution: Change: It should be the same but it's not... why? |
Summary:
001184e added a new compile-time error that prevents using |
vue3: outUse: 可以解决在dev环境正常,但是在 |
Oh, so that how it is. |
It is possible to change emit() for const emit = defineEmits() ?? because with emit() doesn't work properly, thanks |
I came across this issue, with my custom components, that emit update objects for the v-model. After making sure my props are only used in read only by cloning them to local versions the issue was still present. The solution in my case was to use properties of reactive objects in v-model, rather then using the reactive objects themselves. In script setup of the custom element's parent const data = reactive({}); In script setup of the custom element // clone is an implementation for structured cloning
const data = reactive(clone(props.modelValue));
const updateHandler = () => {
emit("update:modelValue", clone(data));
emit("update", clone(data));
emit("update:valid", isValid());
}; The error referred to the parent component <custom-component v-model="data" /> The working way was to use the reactive object's properties in the model. (that) <custom-component v-model="data.that" /> After modifying all my components to that pattern, production is now error free. Note: I use both script and script setup in my components. |
But how & why does it work? Racking my brain over why it's ok to mutate this way? Thanks! |
Because mutation happens in the parent, where you are not mutating a prop, but a regular variable. ℹ️ The computed getter/setter is a very common pattern for this use case 👍🏼 |
Since so many people respond to this problem, it means that it is indeed a problem |
Version
3.2.31
Reproduction link
gitee.com
Steps to reproduce
(1)create a vue3 project with vite;
(2)write a parent component and a child component in <script setup>, use v-model for parent child component communication;
(3)it goes well in dev env,but occur error in prod env, the error as follows:
What is expected?
I expect that my vue3 project which structured by vite.js will go well when use v-model write in <script setup> in prod dev.
What is actually happening?
Actually, it goes well in dev env but get the follow error in prod dev:
NOTE:when I write it not in <script setup>, this error won't happen;
KeyWord:
The text was updated successfully, but these errors were encountered: