I have a component that I built with useContext.
The problem is that my State (named myCartItems) is always being reset and I don't know why. The idea is to add more elements by calling the function addToCart with a product id. then I am trying to copy the current state, and then add the new product to it. But after I check it, I only get the first element every time.
I tried to use this without useContext and it worked. For some reason, it doesn't work when I use it with useContext.
Here is my component:
import React, { useState, useEffect } from 'react'
import { StyleSheet, Text, View, Image } from 'react-native'
const CartContext = React.createContext();
function CartProvider(props) {
const [myCartItems, setCartItems] = useState([]);
const addToCart = (product_id) => {
let tempArray = [...myCartItems];
const found = tempArray.some(product => product.id === product_id);
if (!found) tempArray.push({ id: product_id, count: 1 });
else {
for (let i = 0; i < tempArray.length; i++) {
if (tempArray[i].id == product_id) {
tempArray[i].count = tempArray[i].count + 1;
break;
}
}
}
setCartItems(tempArray);
}
return (
<CartContext.Provider
value={{
myCartItems,
addToCart,
resetCart
}}
>
{props.children}
</CartContext.Provider>
)}
Why do I end up with only one object in the state myCartItems?
EDIT: *** I think the problem is the component I send the data from, it looks like when I call the same function from the Homepage - it works perfectly, but when I call it from another component, it happens.
import React, { useContext, useEffect, useState, useRef } from 'react';
import { Animated, PanResponder, View } from 'react-native';
import { CartContext } from './provider/CartProvider.js';
export default function DragItem(props) {
const context = useContext(CartContext);
const pan = useRef(new Animated.ValueXY()).current;
const panResponder = useRef(
PanResponder.create({
onMoveShouldSetPanResponder: () => true,
onPanResponderGrant: () => {
pan.setOffset({
x: pan.x._value,
y: pan.y._value
});
},
onPanResponderMove: Animated.event(
[
null,
{ dx: pan.x, dy: pan.y }
],
{
useNativeDriver: false,
listener: (evt, gestureState) => {
}
}
),
onPanResponderRelease: (evt, gestureState) => {
//pan.flattenOffset();
if (gestureState.moveY > 300) {
Animated.spring(pan, {
toValue: 0,
useNativeDriver: false
},
).start();
context.addToCart(props.product_id);
}
else {
Animated.spring(pan, {
toValue: 0,
useNativeDriver: false
},
).start();
}
}
})
).current;
return (
<Animated.View
style={{
transform: [{ translateY: pan.y }]
}}
{...panResponder.panHandlers}
>
{props.children}
</Animated.View>
);
}
**** EDIT This is the CartContext component (which holds the data)
import React, { useState, useEffect, useReducer } from 'react'
const CartContext = React.createContext();
function CartProvider(props) {
const [myCartItems, setCartItems] = useState([]);
const addToCart = (product_id) => {
console.log("Added " + product_id + " to cart");
const tempArray = [...myCartItems];
const found = tempArray.some(product => product.id === product_id);
if (!found) tempArray.push({ id: product_id, count: 1 });
else {
for (let i = 0; i < tempArray.length; i++) {
if (tempArray[i].id == product_id) {
tempArray[i].count = tempArray[i].count + 1;
break;
}
}
}
console.log(myCartItems);
setCartItems(tempArray);
}
const resetCart = () => {
setCartItems([]);
}
useEffect(() => {
console.log("CartProvider re-rendered with values: ");
console.log(myCartItems);
}, [myCartItems])
return (
<CartContext.Provider
value={{
myCartItems,
setCartItems,
resetCart,
addToCart
}}
>
{props.children}
</CartContext.Provider>
)
}
export { CartProvider, CartContext }
Using the above component, I can't add the values properly to context. Why is that?
Github: https://github.com/ornakash/shelf Many thanks
Issue is updating state in parent rerender child which is causing the responder to recreate so instead of using useState you can use useReducer.
I modified your code:
https://snack.expo.io/@nordup/pan
Maybe there is a way to avoid to use useReducer, but is will work.
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.