Deleting an object by key doesn't update the vue component - vue.js

I am trying to delete a object using its key and expecting to update the component. I am using vuex.
Here is how I am trying
My object structure is something like this
115:Object
116:Object
I have the key (115, 116) so I am trying to delete them.
delete state.fixture[i]
This code delete the object but the problem is component is not updated even though state of fixture has changed now. How can I update it?
Thank you.

Use
import Vue from 'vue'
Vue.delete(state.fixture, i)
Vue.delete
Delete a property on an object. If the object is reactive, ensure the deletion triggers view updates. This is primarily used to get around the limitation that Vue cannot detect property deletions, but you should rarely need to use it.
The function takes an object and a key to delete from the object.
If you are interested in adding a new property to an object, check Vue.set

Related

How to handle changing props inside a component

I'm making a Form wrapper and I'm wondering how to handle data object prop.
From what I have seen out there, there are some (like FormKit) that mutate the prop object that holds the data. This is not a recommended way according to the official docs. Then there are those (like VueFormulate) that create a shallow copy of the data object before emiting the changed object. To support nested data object you need to deep copy the data object on every change. This seems wasteful with large forms.
Is there an alternative where you don't deep copy an object and you don't mutate object prop?
You could possibly use v-model. as the docs will say, it's shorthand for the child component having a property bound from the parent and when a change event occurs you emit an update event from the child to the parent to have the parent update the property, and the child will subsequently sync to the new value.
ie:
childComponent *has value change*
onChange (value) => this.$emit("updateValue", value)
parentComponent *recieved "updateValue" event*
onUpdateValue(value) => this.parentValue = value

Vue, separate out component templates

I have got a rather large template at the moment for my component. I want to separate aspects of this into it's own component.
However i'm struggling to pass data to this component. I still want to be able to manipulate the data within the child and have the data in the parent update. So for example if I pass in an object, and then use v-model within the child on a textbox, the changes should reflex within the parent.
So, i'd assume as I loop through the list of objects I would v-model them into my child component, like so:
Main.vue
<card v-for="quote in quotes" v-model="quote"></card>
And then of course accept the input within the new model:
Card.vue
export default {
props: [ 'input' ]
}
However i'm getting the following error and I can't really make sense of it.
You are binding v-model directly to a v-for iteration alias. This will not be able to modify the v-for source array because writing to the alias is like modifying a function local variable. Consider using an array of objects and use v-mode
l on an object property instead.

What exactly does mobx-react-lite's "useLocalStore" hook do, and why is it (only sometimes) needed?

Within the mobx-react documentation there are variations in how stores are created. For example, on the React Context page:
In the first code sample, the store is instantiated with useLocalStore:
const store = useLocalStore(createStore)
In the second code sample, the stores are initiated by directly "newing" the stores":
counterStore: new CounterStore(),
themeStore: new ThemeStore(),
By inference, the first is a "local" store (and thus needs useLocalStore), and the second is a "global" store and thus doesn't. However, it is not clear why this is, and what the subsequent differnce in behaviour is.
Why is useLocalStore not needed in second example, and what difference does this make to the behavior of the stores and mobx within React?
Thanks for any input
OK, I found the answer. useLocalStore turns a javascript literal into a store with observable properties. This is not needed if a store is created from a class object with observable attributes.
Thanks to #freddyc for the answer
useLocalStore has been deprecated in favor of useLocalObservable, see here.
Links from the question are no longer valid, mobx-react docs are now here:
https://mobx.js.org/react-integration.html
useLocalObservable(initializer, annotations)
is just a shorthand for:
useState(() => observable(initializer(), annotations, {autoBind: true}))[0]
useLocalStore is almost the same, but it was deprecated because it wasn't as practical.
Why is this needed?
useState() is the main way to store a variable in React.
observable({...}) is the main way to create observable objects in Mobx.
And when using Mobx+React you'll often need the useState + observable combo, so it is nice to have a shorthand.
When is it not needed?
If you are using a class to create your store then you don't need the observable wrapper and you can simply do:
const myStore = useState(() => new MyStore())[0];
If you are using React class components you can save the store on a class field.
class MyComponent
{
myStore = new MyStore();
render() {...}
}
Bonus tip:
Why do we use useState for memorizing values instead of useMemo?
useMemo is meant to be used more like a cache for performance optimization, rather than for storing app state.

V-Model not cleansed when adding Object to array (Vue-Js)

I'm trying to add objects (simple key-value pairs) to a list.
However, the v-model is still bound to the previously added objects, so if I add "ObjectOne" vith "ValueOne", then try to add "ObjectTwo" with "ValueTwo", "ObjectOne" gets edited AND "ObjectTwo" gets added.
I am by no mean an expert in Javascript, so it might not be related to VueJS.
I can obviously make this work with a method per list .
The point is that my model has multiple lists of key value pair to be edited, so I tried making a generic method :
addToList: function(value, list){
console.log("Adding " + value + " to list "+list);
list.push(value);
value={};
},
This method works if used on "simple" lists (like an array of string), but not on "objects" list.
My guess is that as I try to clean "value" instead of "this.value", the reference still points to the same object, but since I don't know what "value" will be when called, I don't know how to do this.
Here is the fiddle with a re-creation of my issue.
My objective would be to be able to use the "addToList" function to add to any list, without having to re-write a function for each list.
Thank you for your help.
The above behaviour is because you are updating the value of same object whenever you add a new todo task.You need to set your object again to add new values as below.
addToList(value, todos){
this.todos.push(value);
this.anotherTodo={ text:'',
done:'false'}
}
Working fiddle here.
I post this as an answer, but if someone has a better way to do it, I'm all hear.
I solved the way by adding a watch on my list. When the list changes, I clean the model object that's added to it.
In my production work, I had to add a computed property, since I can't add a watch on an object's property, then a watch on said computed property :
watch:{
todos(){
this.anotherTodo={};
},
fiddle as demo

Vue: Forcing child component to react to changes in its prop (which is a dictionary)

I am currently generating a table which lists problems encountered during the selected test using a component generated with this code:
<tr is="entry" v-for="problem in problems" :key="problem.id" v-bind:foo="problem"></tr>
Each problem corresponds to an item whose relevant information is contained within the problem dictionary and referenced in the first few columns of the table. Since the same item can have multiple problems, the same item can appear in multiple rows of the table. Now, each row features some buttons which allow you to modify the underlying item so as to fix the problems.
Whenever I modify one of those underlying items I need to modify it in all the rows, which i do by calling a function in the parent component, but modifying the data inside of the dictionary does not seem to trigger any of my watches or computes inside of the child component, which currently looks something like this:
Vue.component('entry', {
props: ['foo'],
data: function(){
//does some computations
return data
},
watch:{
foo: function(){
this.recompute_entry()
},
},
methods:{
//various methods, including:
recompute_entry: function(){
//updates the data according to changes brought to the entry
},
},
});
I have attempted to include a different prop which i could bind to an entry in a list in my parent component but, besides being pretty clunky, that didn't end up working either, which makes me think I might've gotten something wrong with my component.
Ultimately, I have relied on the fact that v-for iterates through my list in an orderly fashion, which combined with the fact that I generate no other children in my parent component means that a child component would have the same index in my component's children array as it would in my problems array. Therefore I can use this:
this.$children[problem_index].recompute_entry();
Which kind of feels hack-ish and unreliable, but actually works, for once. Is there no alternative safer method to recalculate my child components based on changes made to their props? I really feel there has to be.
I probably would need to see the exact implementation but it sounds like you need to clone your dictionary to trigger the prop change, ie:
let newProblem = Object.assign({}, this.problem);
// change any nested property
newProblem.some.value = 1
// assign back the cloned and modified dictionary
this.problem = newProblem