im making a inventory system at Vue Js using Nuxt. im trying to make a function that find in the invendory and if the item exist in the inventory the quantity increase in one. The problem? the function is runs successfully but i can not see changes in my V-for list but if im push other object in my array the v-for loop is updated whit the new data.
<script lang="js">
import Vue from 'vue'
import Navbar from '../../components/Navbar'
export default Vue.extend({
components: {
Navbar
},
data(){
return{
products: [
{ name: 'abrazadera', id: 0, image: "https://carritoferretero.com/wp-content/uploads/2018/05/products-abrazadera-de-arranque-carrito-ferretero_2.png", price: 20},
{ name: 'tuerca', id: 1, image: "https://cdn.homedepot.com.mx/productos/819576/819576-d.jpg", price: 40},
{ name: 'martillo', id: 2, image: "https://cdn.homedepot.com.mx/productos/680442/680442-d.jpg", price: 50}
],
venta: [
]
}
},
methods: {
addProduct(id, index){
let busqueda = this.venta.find( item => item.id == id)
console.log(busqueda)
if(typeof(busqueda) == 'undefined'){
let newObj = this.products[index]
newObj.cantidad = 1
this.venta.push(newObj)
} else {
busqueda = this.venta.findIndex( element => element.id == id )
let newObj = this.venta[busqueda]
newObj.cantidad = this.venta[busqueda].cantidad + 1
this.venta[busqueda] = newObj
}
}
}
})
</script>
in my "addProduct" function im find a product in my "venta" inventory if item does not exist im add a product in my inventory else im add + 1 quantity. the function is working correctly but the rendering vfor does not is updating. The v-for list is updating only if im add a new element using "arrayelement.push"
any idea for solve this? thanks for the answers
Vue 2 can't detect changes to existing items in an array when made the usual way; here's the full explanation. You'll need to change this line:
this.venta[busqueda] = newObj
to:
this.venta.splice(busqueda, 1, newObj)
(You can also use Vue.set, but splice is at least still a standard array operation.)
Related
I've got a counter array, containing 3 objects.
const [counter, setCounter] = useState([
{ id: 0, count: [] },
{ id: 1, count: [] },
{ id: 2, count: [] }
])
Theres then 3 buttons that when pressed call the following function.
const update = (i, text) => {
setCounter(currCount =>
currCount.id === i
? { id: i, count: [...counter[i].count, text] }
: currCount
);
};
The buttons pass "i" which is 0,1,2 corresponding to the 3 object ids and "text" which is the error text.
The function should update the specific object from the array adding the new error text to that id's count array.
I cant seem to get this to work though, it keeps returning undefined.
Any help is appreiciated.
The useState dispatch function (setCounter in your case) replaces the whole state with the value it is provided with.
In your example, you need to recreate the whole array like so:
const update = (i, text) => {
setCounter(currCounter =>
[
...currCounter.filter(count => count.id !== i), // the old counter state without the one we want to change
{ id: i, count: [...currCounter[i].count, text] }
]
);
};
In this below example, I want add or remove the products array elements from object3 and need to updated in react hooks state.
I have tried with filter method inside setter for deleting an element but it won't work. can anyone pls help to do with efficiently.
const myValue = {
object1: {},
object2: {},
object3: {
products: [{
name: 'Fruits',
id: '1'
},
{
name: "Vegtables",
id: '2'
}],
number: 1
}
}
You can extract out the object3 as another variable, do whatever operations you want to do and set state again combining it with the current state value.
const {object3} = myValue;
// for example if you want to filter based on condition for id
const modifiedProducts = object3.products.filter((item) => item.id > '1');
setMyValue({
...myValue,
object3: {
...object3,
products: modifiedProducts
}
})
I would also suggest making multiple states for each object if all objects are independent from each other. Here if some component only depends on object1, ideally it should not re render when object 3 updates.
I'm trying to display sub Products of the main product so what I have tried is to get the product code from the URL and try to fetch sub-products that match the main product code
List of Products and Sub products
const data ={
product:[
{
title:'Product1',
slug:'001',
category:'shirt',
image:'./../../public/image1.jpg',
},
{
title:'Product2',
slug:'002',
category:'shirt',
image:'./../../public/image2.jpg',
},
],
subProduct:[
{
title:'subProduct1',
slug:'001',
image:'./../../public/image01.jpg',
price:70
},
{
title:'subProduct2',
slug:'001',
image:'./../../public/image02.jpg',
price:200
},
{
title:'subProduct3',
slug:'002',
image:'./../../public/image03.jpg',
price:170
},
{
title:'subProduct4',
slug:'002',
image:'./../../public/image04.jpg',
price:150
},
],
}
const slug = '001';
const product = data.product.find(x => x.slug === slug);
const subProducts = data.subProduct.filter(function(x) {
return x.slug == slug;});
console.log(subProducts.title)[enter image description here][1]
the issue is it shows Undefined when I try implement like {subProducts.title}
but when I console.log(subProducts) I get Array of subProducts that match with the slug of the Main Product
subProducts is an array of objects. You're trying to get to title attribute of each item in that array but what you are actually doing with subProducts.title is that you're trying to reference a title property on an array, which yields undefined, because the array has no such attribute. The array contains objects as individual items and those are the ones that have the title attribute.
So in react (which is part of next.js) when you need to render an array, try something like this:
const Component(props) => {
const subproducts = [{title: 'Foo'}, {title: 'Baz'}]
return (
<div>
{
subproducts.map((subproduct) => (
<div key={subproduct.title}>{subproduct.title}</div>
))
}
</div>
}
The key tag is required by react. More on this here
I'm trying to update an array property in an array of objects using react hooks, as we all know when we need to update the state based on a previous state we use the function set"MypopertyName"
as shown below:
My code:
const [MenuList, setMenuList] = useState([
{
id: 0,
title: "sushi",
desc: "finest fish and vegies",
price: "$22.99",
amount: 1,
},
{
id: 1,
title: "shneitzel",
desc: "a german specialty",
price: "$50.99",
amount: 1,
},
{
id: 2,
title: "pizza",
desc: "an italian specialty",
price: "$100.99",
amount: 1,
},
{
id: 3,
title: "pasta",
desc: "an italian specialty",
price: "$200.99",
amount: 1,
},
]);
my problem that I wanna change the amount of the meal based on clicks of the user so here is what I tried:
const onClickHandler = (id) => {
for (const key in MenuList) {
if (MenuList.id === id) {
return (MenuList[key].amount = MenuList[key].amount + 1);
}
}
};
I know that the reactivity system of react only works when I call setMenuList() I tried that but it doesn't work besides I wanna update the specific object immutably so I need to use the function syntax like this:
setMenuList((prevMenuList)=>{
//my code
})
also, I didn't manage to get it work, sorry guys I'm one of the old gurus that used the class-based components for a long time you know with the state={} and so on the whole new hooks concept is new for me.
So any help would be appreciated and thank you in advance.
The use of the function-based setter
setMenuList((prevMenuList)=>{
is useful when the function may be called when the menuList currently in its scope is not what's currently being rendered - for example, for when the function is called after an API call finishes. This is completely different from React's need to not mutate state, which requires another approach entirely.
Map the state array, and when the ID matches, return a new object with the amount incremented.
const onClickHandler = (id) => {
setMenuList(
menuList.map(
obj => obj.id !== id ? obj : ({
...obj,
amount: obj.amount + 1
})
)
);
};
I initialize component state with the store state which pulls api data.
I filter the array of data by object name. This then will setState with the object chosen by the user via a button. This works, all objects change without issue. The problem I cannot for the life of me figure out is what I want is to setState onClick with a nested array of objects associated with the category. So each category object has a nested subCategory array which holds many subCategories.
So a generic example would be:
const arr = [
{ name: 'Do', id: 1, sub: [{sub_id: 1, something: 'dog'}, {sub_id: 1, something: 'cat'}] },
{ name: 'Re', id: 2, sub: [{sub_id: 2, something: 'bird'}, {sub_id: 2, something: 'mouse'}] },
{ name: 'Me', id: 3, sub: [{sub_id: 3, something: 'lion'}, {sub_id: 3, something: 'moose'}] }
];
class BrainFart extends Component {
constructor(props) {
super(props)
this.state = { foo: [] }
}
handleArray() {
const stuff = arr.filter(c => c.sub)
this.setState({foo: stuff})
}
}
This will not set state with the nested array of sub...
Any thoughts?
Thank you
Update your handleArray function to:
handleArray() {
const stuff = arr.filter(c => c.sub);
this.setState({ foo: [...this.state.foo, ...stuff] });
}
Note the change when setting new value for foo property on component state. In this case we create a new array based on the previous and new data (stuff).
Read more on react docs about how to modify component state.
Current problem is setting foo to the output of foo.push(stuff).
The push() method adds one or more elements to the end of an array and returns the new length of the array.
Read more about push