Vue 2 failing to retain component data upon page refresh

I've encountered a peculiar issue with Vue (v2.6.14) where I'm trying to create a new array based on one received as a prop. Here's the code snippet that's causing the trouble:

props: { employees: Array },
data() {
  return {
    sortedEmployees: [],
  };
},
mounted() {
  this.sortedEmployees = this.employees.slice(0);
},

The main goal here is to generate a separate reference for the employees array so that I can sort it for later display without modifying the original array. I don't need to clone the actual objects inside the array since I won't be changing them.

The issue arises when the app 'hot reloads' due to a code change – everything works perfectly, the hook is triggered and the component data is set correctly. However, when I refresh the page in the browser, even though the hook is still executed, the component data isn't properly set, resulting in an empty array. One way to resolve this is by setting up a watcher for the prop to ensure the data is properly updated, but my focus here is on understanding why this discrepancy occurs. If the hook is being called during a page refresh, why doesn't it set the data as expected, like it does during 'hot reloading'?

I'm working with a simple setup created using vue-cli without any complex configurations. Any insights into what might be causing this behavior would be greatly appreciated.

Answer №1

It seems like the employees are being loaded asynchronously, correct?

Without knowing the exact structure of your application, the issue typically arises as follows:

The mounted hook is triggered when the component mounts. If the employees are loaded asynchronously in the parent component, the mount hook is called before the async call is resolved, resulting in an empty array being copied at that time.

A watcher can resolve this issue by triggering once the async call is completed (updating the employees array).

A similar scenario occurs during hot reloads. When a hot reload happens, the mounted hook runs again – but this time the employees array is already filled with values, ensuring the correct array is copied in the mount hook.

Update

If you prefer to avoid using watchers, you can wrap your component like this:

<your-component
  v-if="employees.length > 0"
  :employees="employees"
/>

Keep in mind that the copied employees array within your component is still not reactive; it simply duplicates the array when it has more than one value. Using a watcher would be more advisable in this case.

If you opt for watchers, ensure to include the immediate: true option. This guarantees that the watcher is also triggered upon rendering (and hot reloads).

Summary

If you truly need to duplicate the array, utilize watchers (with the immediate: true flag).

For sorting purposes only, consider utilizing the computed property solution recommended by @Sebastian Scholl.

Answer №2

It seems like the component is refreshing (resetting) when the prop changes, but it is not remounting. This is why the array resets to its default state ([]), whereas on hot-reload the entire page reloads.

Try the following, and if it doesn't resolve the issue, I recommend using a Watcher.

<template>
  <div>
    sorted: {{ sortedEmployees }}
    <br />
    not sorted: {{ employees }}
  </div>
</template>

<script>
export default {
  props: {
    employees: Array,
  },
  data() {
    return {
      sortedEmployees: Array.from(this.employees),
    };
  }
};
</script>

Another approach is to create a Computed method and add any filtering/sorting logic inside that method:

<template>
  <div>
    <input v-model="sortKey" />
    sorted: {{ sortedEmployees }}
  </div>
</template>

<script>
export default {
  props: {
    employees: Array,
  },
  data () {
    return {
      sortKey: ''
    }
  },
  computed: {
    sortedEmployees() {
      return Array.from(this.employees).sort(this.sortingFunction);
    },
  },
  methods: {
    sortingFunction(a, b) {
      // sorting function using this.sortKey
    }
  }
};
</script>

UPDATED ANSWER

I made some changes to the example code and managed to get it working as you described.

App.js I updated the code so that the employees array is updated after 3 seconds:

<template>
  <div id="app">
    <Dashboard :employees="employees" />
  </div>
</template>

<script>
import Dashboard from './components/Dashboard.vue';

export default {
  name: 'App', 

  components: { Dashboard },

  data () {
    return {
      employees: [
        {
          employeeId: '1',
          firstName: 'Leite',
        }
      ]
    };
  },

  methods: {
    updateEmployees () {
      this.employees = this.employees.concat([
        {
          employeeId: '2',
          firstName: 'Jacinto',
          
        },
        {
          employeeId: '3',
          firstName: 'Capelo',
        }
      ]);
    }
  },
  
  mounted () {
    setTimeout(this.updateEmployees, 3000)
  },
};
</script>

Dashboard.js The updated() lifecycle hook runs whenever data changes are detected (props and data properties). This effectively detects the change in the prop passed by the parent App.js component and re-renders the data - unlike the mounted hook which only runs once per page load.

<template>
  <div id="dashboard">
    <div
      v-for="(employee, index) in sortedEmployees"
      :key="employee.employeeId"
    >
      {{ employee.firstName }}
    </div>
  </div>
</template>

<script>

export default {
  name: 'Dashboard',
  props: { 
    employees: Array 
  },
  data() {
    return {
      sortedEmployees: Array.from(this.employees)
    };
  },
  updated() {
    this.sortedEmployees = Array.from(this.employees)
  }
};
</script>

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

tips for extracting elements from lists on sharepoint using CAML QUERY

In the project I'm working on, there are three lists: ListeBatiment with 2 fields (IDListeBatiment, CodeBatiment) ListeEtage with 3 fields (IDListeEtage, CodeEtage, IDListeBatiment) ListeLocal with 3 fields (IDListeLocal, CodeLocal, IDListeEtage) F ...

Guide on converting data from PHP to JSON using JavaScript

Here is some data that I need to loop through: image1 url1 description1 image2 url2 description2 image3 url3 description3 image4 url4 description4 image5 url5 description5 After looping through the data: var imagesDataArray = [ { src: &apo ...

Challenge encountered when attempting to detect multiple submit buttons using jQuery

I am currently attempting to identify which of the four submit buttons was clicked using jQuery 1.7.2. When any one of three specific buttons is clicked, I want an alert box to appear displaying the value of that particular button. Below is the HTML code s ...

How can datatables format a column by pulling from various sources? (Utilizing server side processing

Struggling to implement server-side processing with concatenated columns and encountering SQL errors. Came across a post discussing the issue: Datatables - Server-side processing - DB column merging Would like to insert a space between fields, is this ac ...

Function anomalies triggered by delayed setState updates with React Hooks

Creating a Quiz app with React involves fetching questions as an array and managing the following states: An array containing all question details - statement, options, chosen answer, status (answered, marked for review, unvisited); An object holding info ...

The analytics event code is visible in the source code, but is not displaying in the console

I am facing an issue with a website built on Umbraco and it has me completely stumped. I have set up event tracking for Analytics on several download buttons, and while most of them are functioning properly, there is one button causing me trouble. When I ...

Vue components failing to render in Laravel application

Currently experiencing an issue in Laravel where Vue components are displaying/updating locally but not on the server. Despite having all necessary packages of Vue and Node installed on the server, I can't seem to figure out what the problem is. Here ...

Sending a notification alert directly to the client's web browser

My goal is to develop an application that allows Super users to notify other users by providing access to content, such as a PDF file, when they click on a link. For example, in the scenario where a teacher wants to share a PDF with students, this applica ...

Setting the box width to "0" will actually render as a width of "1"

While attempting to create a box new THREE.BoxGeometry(opening.geometry.xLength, opening.geometry.yLength, opening.geometry.zLength) a situation arises where a box with 0 width is produced. new THREE.BoxGeometry(0, 1, 1) Surprisingly, it ends up render ...

Uncovering Inline Styles Infused with Javascript for Effective Debugging of Javascript Code

SITUATION: I have recently inherited a website from the previous developer who has scattered important functions across numerous lengthy JS files. I am struggling to track down the source of an inline CSS style within the JS or identify which function is d ...

Guide to implementing a click-triggered notification using JavaScript

Can anyone assist me with a JavaScript issue regarding applying toast notifications? I need guidance on implementing an onClick toast using JavaScript. The toast should only appear when a specific condition is false; if the condition is true, the page sho ...

What is the best way to switch the site header in JavaScript or jQuery?

I have created a Bootstrap menu design and I am looking to add a sliding functionality to it. My goal is to hide the menu when scrolling down and display it when scrolling up (slide-down / slide-up). For implementing this feature, I plan to utilize jQuery ...

Importing glTF files in Three.js while hiding the background

On Three.js, there are 2 sample scenes demonstrating how to import gltf models. Both utilize an RGBELoader function to set up the background. new RGBELoader() .setDataType( THREE.UnsignedByteType ) .setPath( 'textures/ ...

Tips on avoiding a tangled mess of if statements in my Bootstrap 4 dropdown sorting code

As a beginner self-studying JavaScript/jQuery, I am looking to simplify and shorten my code while maintaining readability. However, I am struggling to find a way to achieve this. The issue lies in the excessive if statements I have used, and I believe that ...

A simple guide on logging into Discord with token using the Selenium library in Python

I created a Python code using the selenium module to log in to Discord using a token number. The token number needs to be added to localStorage, so I used JavaScript code to add it successfully. However, upon checking Application -> localStorage -> h ...

"Unlocking the Power of Node Modules: Ensuring Libs are Access

Imagine a scenario where project B relies on a node module called A. The structure of module A is as follows: ./node_modules/A ./src ./shared bar.js foo.js .... etc .... Within project B, I want to utilize bar.js a ...

Guide on navigating through a specific section of a webpage in Selenium by utilizing the JavaScript executor

I understand that we can utilize the following script to scroll down on a webpage: (JavascriptExecutor) driver.executeScript("window.scrollBy(0,1000)"); However, I have a specific section on the page with a scroll bar. To reach the last element in that s ...

Invoking Javascript Functions using their names

Suppose I have the following element on my page... <span data-function="DoSomething">Click</span> ... and then add the following to my page header... $(document).ready(function() { $('[data-function]').each(function() { ...

Frontend is refusing to remove items from the shopping cart, while the backend is functioning properly in doing so

I've been working on a shopping cart project using Vanilla JS. The interface handles DOM logic, while the backend deals with array manipulation. The issue I'm facing is with a button that's supposed to remove items from the cart. Despite pa ...

What is the best way to use jQuery ajax to send various row identifiers when updating table data on another PHP page by selecting checkboxes?

When I select both of the green checkboxes, only the most recent table id is sent. The code below includes both the checkbox markup and jQuery function. Checkbox: <div class='md-checkbox has-success'> <input type='checkbox&apo ...