Reactivity in a Vue child component is lost when interacting with a fetched pinia/vueFire object

My goal is to load an item into a child component for editing purposes. The approach I am taking involves passing an itemId from the parent to the child as a prop. In the child component, I use the function store.itemForId(id) to fetch the itemData from a vueFire/firestore collection. While I can successfully retrieve the item document in the child component, it loses reactivity. If there are external updates made to the firestore Document, the collection in the pinia store and the data in the parent get updated, but the item retrieved in the child component does not reflect these changes.

However, when I use the same function in the parent component and pass the item down to the child, the reactivity is maintained. Although this workaround works temporarily, it doesn't fully solve my problem as I eventually need the ability to edit the item. This makes me suspect that the issue lies within the child component itself.

In my setup, I have a pinia store that contains a projectItems Collection and a projectInfo Document. The projectInfo.itemOrder specifies the display order for the items.

The code snippet below shows an excerpt from 'projectStore.js' where the main logic resides:

// projectStore.js
const projectInfo = useDocument(() => doc(db, projectPath))
const { data:projectItems, promise:itemsPromise } = useCollection(() => collection(db, itemsPath))

function itemForId(id) {
  return projectItems.value.find((item) => item.id === id)
}

A snippet of 'MyParent.vue' illustrates how I'm handling the data flow:

<script setup>
  import { useProjectStore } from 'stores/projectStore'
  const projectStore = useProjectStore()
  const { projectInfo, projectItems } = storeToRefs(projectStore)
</setup>
<template>

  <div>Child receives Id, but it's not reactive</div>
  <template v-for="itemId in projectInfo.itemOrder" :key="itemId">
    <IdChild :itemId="itemId" /> 
  </template>

  <div>Child receives Item, and it remains reactive</div>
  <template v-for="itemId in projectInfo.itemOrder" :key="itemId">
    <ItemChild :item="projectStore.itemForId(itemId)" /> 
  </template>

  <div>Raw Item Data, which is reactive</div>
  <div>{{ projectItems }}</div> 
</template>

'IdChild.vue' demonstrates the non-reactive behavior:

<script setup>
  import { useProjectStore } from 'stores/projectStore'
  
  const props = defineProps({ itemId: String })
  const projectStore = useProjectStore()
  const { projectItems } = storeToRefs(projectStore)

  const item = ref(projectStore.itemForId(props.itemId))

</setup>
<template>

  <div>{{ item.name }}, but it's not reactive</div>
  
  <!-- This approach is reactive but seems repetitive -->
  <div>{{ projectStore.itemForId(itemId).name }}</div>

  <div>Raw Item Data, intended for troubleshooting but also reactive</div>
  <div>{{ projectItems }}</div> 
</template>

'ItemChild.vue' was created for troubleshooting purposes and is reactive but lacks editability due to receiving the item as a prop:

<script setup>
  import { useProjectStore } from 'stores/projectStore'
  
  const props = defineProps({ item: Object })

</setup>
<template>

  <div>{{ item.name }}, reactive</div>
  
</template>

I am seeking solutions on how to ensure reactivity with the item within my child components or insights into any nuances regarding reactivity that I might be overlooking.

Answer №1

The reactivity diminishes when the responsive object is promptly accessed within the setup function. This action may be intentional in order to obtain the initial state for an alterable object. However, in the case of a static object that must respond to changes in another object it is derived from, it should be a computed property (hence its name):

const element = computed(() => store.itemById(props.itemId));

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

Issue an alert and refresh the webpage when a file extension upload script is detected

Here is the JavaScript code I'm using to restrict the file type extension during uploads: function TestFileType( fileName, fileTypes ) { if (!fileName) return; dots = fileName.split(".") //get the part AFTER the LAST period. fileType = "." + dots[do ...

Retrieving the values from unspecified keys within an array of objects

Receiving a JSON from an external source with an unpredictable number of keys is the challenge. The structure typically appears as follows: data = [{ id: 1, testObject_1_color: "red", testObject_1_shape: "triangle", testObject_2_color: "blue", testObject_ ...

Passing PHP array to JavaScript in a specific format

After running the code provided, I find that the data returned is in an array format but unfortunately not easily referenced. AJAX: $.ajax({ url: './FILE.php', type: 'post', data: {'action': 'allfolders'}, ...

Leveraging jQuery plugins within an AngularJs application

I am currently trying to implement the tinyColorPicker plugin from here in my Angular app, but I am facing difficulties with it. An error message keeps appearing: TypeError: element.colorPicker is not a function In my index.html file, I have included th ...

Obtain JSON data using a JSONP fetch promise method

As I embark on my journey with react-native, I have chosen the classic example found in the documentation as my starting point... fetch('https://facebook.github.io/react-native/movies.json') .then((response) => response.json()) .then((res ...

Reveal concealed fields following the selection of a specific option

I'm looking to create a bookmarklet that will automatically fill in values when clicked. Currently, I can select values using: document.getElementById('component').value="IAE-Data Agent"; document.getElementById('component').onch ...

When executing a JavaScript program, an error with the message 'MODULE_NOT_FOUND' appeared, causing the internal module loader in Node to throw an error at line 1145

node:internal/modules/cjs/loader:1145 throw err; ^ Error: Module 'C:\Users\sande\3D Objects\JavaScript-Lesson\lesson08.js' not found at Module._resolveFilename (node:internal/modules/cjs/loader:1142:15) at Mo ...

Can cucumber steps be executed conditionally within a single scenario?

I would like to streamline my testing process by using one feature file for both desktop and mobile tests. I am looking to run two separate tests, with one tagged as @mobile and the other as @desktop. By doing this, I can avoid creating a duplicate feature ...

Having issues with setTimeout on Chrome for Android when the browser is out of focus. Any ideas for resolving this?

I developed a web application that functions as a messaging system, where users can submit messages and others can receive them. The system operates through AJAX, with the front end using JavaScript to interact with a PHP backend. Everything runs smoothly ...

How can jQuery incorporate additional selection criteria for a parent element?

How can I apply a specific criteria to a node that has been selected using jQuery? let objDIV = $("#selindividual").parent(); After retrieving the DIV, I want to target the following: button:contains(\"Submit\") If I had to do this in ...

Tips on retrieving a <list> from an MVC controller and passing it to the view with jQuery and AJAX

How can I retrieve a list from an MVC controller to a view using jQuery AJAX without getting the error message [object Object]? Here is my AJAX code: $.ajax({ type: 'POST', contentType: 'application/json; ch ...

Using ReactJS in conjunction with MaterialUI version 3, implement a select feature directly within a

Currently utilizing Reactjs along with MaterialIU version 3 (not to be confused with v4), my objective is to create a Table by employing [array].map method, and embed a Select inside each TableCell. The aim is to assign a specific percentage separately for ...

Error: ajax is not defined and needs to be declared (repeated twice)

Currently, I have a form that requires processing using Ajax. <script type="text/javascript" src="http://code.jquery.com/jquery-1.9.1.js"></script> <div class="column1"> <form class="form box" action="javascript:networkCheck();" ...

How can I execute a HTTP POST request in Node.js using MongoDB and Mongoose?

I have completed my schema setup and now I am looking for guidance on how to perform an HTTP POST request. I am currently utilizing MongoDB with the Mongoose framework. By implementing this, I aim to view the JSON data I have posted when accessing localhos ...

creating custom styling for elements within a map function

Within my React application, I am using the map JavaScript function to render a div multiple times. Each element needs to have a specific width set via CSS. The className for each div is unique. Here is how I am rendering the divs: {this.props.face_clicke ...

submitting a POST request with JSON payload including an array

Resolved. To solve this issue, you need to set the contentType to 'application/json' and use JSON.stringify(obj) instead of obj. However, keep in mind that you may need to adjust how you retrieve the data on your server, depending on the language ...

Enhance the efficiency of AngularJS search filtering

With nearly 2000 rows on this page, I am using AngularJS filter to search for items containing the typed strings. However, I have noticed that the efficiency is poor when typing just one character into the input control. Does anyone have suggestions for im ...

Troubleshooting Problems when Resizing Objects in AngularJS and d3js

In my current project, I am working on integrating AngularJS with d3 for drag and resizing functionalities. So far, I have successfully created a draggable rect object within an SVG element that can be resized using handles. However, I have noticed that re ...

What are some strategies for optimizing React performance when managing controlled input from numerous components?

Building a Parent component with multiple child components, each passing data to the parent for an API call. The structure is as follows: const MainComponent = () => { const [child1input, setChild1Input] = useState(""); const [child2input, setChild ...

I'm looking to create a Slider component using @material-ui/core that has a track divided into two sections with distinct colors for the left and right sides. How

When the slider ranges from -10 to 0, I want it to display in red. For values between 0 and +10, I would like it to be shown in green. Is there a way to implement this color change using the <Slider /> component from @material-ui/core? ...