adding item to cart in reactjs using localStorage - reactjs

whenever i am adding item in cart it get added in cart on page but not on localstorage on first click but my total price updates according to the item selected price. And when i add next item it gets added on localstorage as well as the first selected item gets added.
Everything is working properly but problem is on first click item is not displaying on localstorage.Please help , i am stuck with this problem since more then 2days,Thank you in advance!
componentDidMount() {
var localItems = JSON.parse(localStorage.getItem('items')) || [];
this.setState({
selectedProduct : localItems
});}
addToCart(image, name, type,price, id) {
const found = this.state.selectedProduct.some(el => el.id === id );
const obj = {image,name,type,price,id};
this.setState(
{
selectedProduct: found ? this.state.selectedProduct : [...this.state.selectedProduct,obj],
isAdded: true,
totalPrice : found ? this.state.totalPrice : this.state.totalPrice + parseInt(price, 10)
},
() => {
localStorage.setItem('total',this.state.totalPrice);
localStorage.setItem("items", JSON.stringify(this.state.selectedProduct));
}
)
}
Please see these images of my output for more clearification of statement
When first item is selected (on first click):
When i click on Second Item:

You can't use this.state.totalPrice inside the second parameter of setState, it will still be the old variable.
Instead do it all inside a callback method in setState, that way you'll get correct access to the previous state:
addToCart(image, name, type, price, id) {
const obj = {
image,
name,
type,
price,
id
};
this.setState((prevState) => {
const found = prevState.selectedProduct.some(el => el.id === id);
const selectedProduct = found ? prevState.selectedProduct : [...this.state.selectedProduct, obj];
const totalPrice = found ? prevState.totalPrice : prevState.totalPrice + parseInt(price, 10)
localStorage.setItem('total', totalPrice);
localStorage.setItem("items", JSON.stringify(selectedProduct));
return {
selectedProduct,
totalPrice,
isAdded: true
};
})
}

Related

DropDownPicker worked after clicking second time only

I have two dropdown picker. One is dependent on another one. If I click color on one dropdown another dropdown should show list of colors but its not working properly. If I click on first dropdown first time and select color second dropdown shows nothing but when I click on color again it shows the result in second dropdown.
Not sure why its happening
Here is my slack link:
https://snack.expo.dev/#anamika1593/carlist
I fixed your code. Your problem was that you set the state in function and then you used the variable from the state "selected" but when you set the state. The Variable doesn't change immediately and you used "old value" from the state.
if (item.label === "Color") {
const colorData = [...new Set(data.map((val) => val.car_color))];
var color = colorData.map(function (val, index) {
return {
id: index,
value: val,
label: val,
};
});
return setChildValue(color)
} else if (item.label === "Model") {
const modelData = [...new Set(data.map((val) => val.car_model))];
var model = modelData.map(function (val, index) {
return {
id: index,
value: val,
label: val,
};
});
return setChildValue(model)
} else if (item.label === "Year") {
const yearData = [...new Set(data.map((val) => val.car_model_year))];
var year = yearData.map(function (val, index) {
return {
id: index,
value: val,
label: val,
};
});
return setChildValue(year)
}
You have to do it like this and use item that you put in the function.
Fixed code

Problem checking if an item exists in cart

hello I've been having a problem with checking if an item already exists in the cart. if so I want only the quantity to be updated for some reason it keeps adding the item as a new item even if it exists. This is what I've been doing:
// Adding Items to cart
const onAdd = (product, quantity) => {
const checkProductInCart = cartItemsFromLocalStorage.find((item) => item.id === product.id);
setTotalPrice((prevTotalPrice) => (prevTotalPrice + Math.round((product.price * quantity)*100)/100));
setTotalQuantities((prevTotalQuantities) => prevTotalQuantities + quantity);
if(checkProductInCart) {
// eslint-disable-next-line
const updatedCartItems = cartItemsFromLocalStorage.map((cartProduct) => {
if(cartProduct.id === product.id) return {
...cartProduct,
quantity: cartProduct.quantity + quantity
}
})
setCartItems(updatedCartItems);
} else {
product.quantity = quantity;
setCartItems([{ ...product }, ...cartItems]);
}
toast.success(` ${product.name} added to the cart.`);
}
Seems like the issue is on your cartItemsFromLocalStorage.map implementation. The map function should return the product even if it isn't the one you're looking to update. Try updating that map to
cartItemsFromLocalStorage.map((productOnCart) => {
if (productOnCart.id === product.id) {
return { ...productOnCart, cartProduct.quantity + quantity }
}
return productOnCart
})
If you don't return anything your list will be full of undefined objects

How to remove the the previous instance created in React useEffect()

This is my useEffect().I am making a website using React and alan voice recognition.
What this useEffect() does is when someone enters the country it creates an alanBtn which is basically a button.Now the problem is that when the user selects another country the previous button stays on the page and on top of it a new button is made.
What I want to do is whenever a user selects a different country it destroys the previous button instance and then creates new one.
useEffect(() => {
alanbtn({
key: alanKey,
onCommand: ({ command, articles, number }) => {
if (command === "newHeadlines") {
setNewsArticles(articles);
setActiveArticle(-1);
} else if (command === "highlight") {
setActiveArticle((prevValue) => prevValue + 1);
} else if (command === "open") {
const parseNumber =
number.length > 2
? wordsToNumbers(number, { fuzzy: true })
: number;
const article = articles[parseNumber - 1];
if (parseNumber > 20) {
alanbtn().playText("Please try that again");
} else if (article) {
window.open(article.url, "_blank");
alanbtn().playText("Opening...");
}
}
},
}).setVisualState({ answer: country });
}, [country]);
The country is passed as prop to this component.

How to update a state variable in an array in React?

I have this state and I want to update the properties name and location in a dynamic way.
this.state = {
players: [{
name: '',
location: ''
},
{
name: '',
location: ''
}]
}
The idea is that you can click a button to add another/remove a player. Per player, these input fields should appear (which I achieved), but I'm unable to update the state on change.
Preferably something like this (but I'm unable to make it work for this particular case). Unless there's a better way to achieve this of course (I'm rather new in React).
this.handleChange = (event) => { let obj = {...this.state.obj }; obj [event.target.name] = event.target.value; this.setState({obj }); }
Any help will be appreciated!
you can add temporary id value to the player's list and on change pass the target id and the field changes, and change the state accordingly
const onPlayerChange = ({target : { id , name , vlaue}}) =>{
const newPlayersState = this.state.players.map(player=>{
if(player.id === id) return {...player,[name]:value}
return player;
})
this.setState({players:newPlayersState})
}
addPlayer(name, location) {
const players = {...this.state.players};
players.push({
name,
location
});
this.setState({
players
});
}
removePlayer(name) {
const players = {...this.state.players};
this.setState({
players: players.filter(p => p.name != name)
});
}

change of one value in the state react

In the state I have data array that look like this
{
"offers" : [
{
"model": "shoes",
"availability": false,
"id": 1
},
{
"model": "t-shirt",
"availability": true,
"id": 2
},
{
"make": "belt",
"availability": false,
"id": 3
}
]
}
My task is to change the accessibility field. I have a button - change the availability. After clicking it I want to make the availability of a single field changed
changeAvailability = (ailability, id) => {
console.log(ailability)
console.log(id)
const { data } = this.state;
let newData = [...data]
this.setState({
data: newData.map(x => x.id === id ? x.ailability = !ailability : ailability )
})
}
I have created a function that does not work.
My idea was: I click on the element, pass to the element's id and accessibility. In this function, I create a copy of the state. In the right place, I change the availability and I am sending everything to the state.
This function does not work, nothing happens, I have no idea how to fix it
Seems like the map function is returning nothing ...
Could be something like this
changeAvailability = (ailability, id) => {
console.log(ailability)
console.log(id)
const { data } = this.state;
let newData = [...data]
const updateItem = (x) => {
if (x.id === id) {
x.ailability = !ailability;
}
return x;
};
this.setState({
data: newData.map(updateItem)
})
}
I am assuming you want to click on an element which passes an id and availability of an offer, find a matching entry (on the passed id) in the offers array in the state and change the availability of the found object to what you passed in the function.
I recommend using the callback that this.setState() allows you to use, providing a reference to a copy of the previous state, before the setState was called.
changeAvailability = (passedAvail, passedID) => {
this.setState((prevState) => {
// Make a copy of the offers array in the state
const offersArray = prevState.offers
// Find index of matching obj by id
const matchObjIndex = offersArray.findIndex(
(offerObj) => (
offerObj.id === passedID
)
)
// If a match was indeed found
if (matchObjIndex > -1) {
// Find matching obj from index obtained
const matchObj = offersArray[matchObjIndex]
// Change the availibility of the matched obj and obtain a modified obj
const modmatchObj = Object.assign(matchObj, {
availability: passedAvail
})
// Replace the offer obj by index in the offers array.
offersArray.splice(matchObjIndex, 1, modmatchObj);
}
// Finally set state with the updated offers lists
// If no match was found, it will return the old offers array
return {offers: offersArray }
})
}
You can try something like this to make it work:
changeAvailability = (availability, id) =>
this.setState(prevState => {
return {
offers: prevState.offers.map((e, i) =>
e.id !== id ? e : { ...prevState.offers[i], availability }
)
};
});
The issue with your solution is that you shouldn't modify the items you're iterating while doing a map, but you should just return whatever new data you wanna add.

Resources