简体   繁体   中英

React-Native - my state being reset after adding values to the current from specific component (panResponder)

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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM