Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Vue 3, provide() can only be used inside setup()

I have an AppReplyToMessage component that is supposed to send data to the AppSendMessage component to notify it that the message being sent is a reply. I'm doing it as follows; The AppReplyToMessage component:

<script setup>
import { provide } from "vue";
import AppSendMessage from "../AppSendMessage.vue";

let props = defineProps({
    message: {
        type: Object,
        required: true,
    },
});

let message = toRefs(props).message;

const replyToMessage = () => {
    const message = {
        reply: true,
    };

    provide("reply", message);
};
</script>
<template>
  <button@click="replyToMessage">
    Reply
   </button> 
</template>

and in the AppSendMessage component I'm receiving the data as follows:

<script setup>
  const reply = inject("reply", null);
</script>

The code though is not working an I'm getting the error [Vue warn]: provide() can only be used inside setup(). in the console.

like image 548
user3714932 Avatar asked Dec 08 '25 06:12

user3714932


2 Answers

provide should be used at the top level of setup, not within another function within setup.

First create an empty ref, and pass that to the provide function. Then within your replyToMessage function, set the value of the ref when the button is clicked.

<script setup>
import { provide, ref } from "vue";

// ...

const reply = ref(null);
provide("reply", reply);

const replyToMessage = () => {
    const message = {
        reply: true,
    };

    reply.value = message;
};
</script>
<template>
  <button @click="replyToMessage">
    Reply
   </button> 
</template>

Docs

like image 160
Matt Schlosser Avatar answered Dec 09 '25 20:12

Matt Schlosser


Disregarding the small errors you have in your source code, like forgotten import { inject } from "vue" in the AppSendMessage component, you have two important design problems.

  1. The Vue props are readonly. Do not try to mutate the props in components!

  2. The Vue warning states that you should run provide() only from setup() or from <setup script>.

You call setup() from a lambda function.

const replyToMessage = () => {
    const message = {
        reply: true,
    };

    provide("reply", message);
};

You should run provide("reply", message) directly from <setup script>

  1. And then, you declare a new message constant in the lambda function, which has no relation to your message prop.

Please read the Vue Docs about Components and Provide / Inject thoroughly and check the SFC Playground with Provide / Inject example.

Here is the SFC Playground with the solution

const reply = ref({});
provide("reply", reply);

const replyToMessage = () => {
    reply.value.message = props.message;
    reply.value.reply = true;
};
like image 40
Tolbxela Avatar answered Dec 09 '25 18:12

Tolbxela