Quantcast
Channel: Active questions tagged react-native+typescript - Stack Overflow
Viewing all articles
Browse latest Browse all 6213

React Native elements not rerendering after state change

$
0
0

I have been looking at this error for 2 days now, and I cannot seem to figure out how and why this is not working. I have a FlatList of ProductComponent elements in my app which can be bought and sold through the push on a TouchableHighlight component defined in the ProductComponent.
Below is the code of my FlatList component and the ProductComponent it renders:

The FlatList component:

    const ProductList: React.FC = () => {    const energyResources = useSelector((state: RootState) => state.energyResources).asImmutable();    const dispatch = useDispatch<RootDispatch>();    const coins = useSelector((state: RootState) => state.coins).coins;    const purchaseItem = (item: IEnergyResource): void => {        if (coins > item.price) {            dispatch.energyResources.increaseAmountOwned(dispatch.energyResources, item);            dispatch.coins.buy(dispatch.coins, item.price);            Alert.alert('Gekocht!','Je hebt zojuist de energiebron '+ item.name +' gekocht, '+'\nJe hebt nu nog €'+ coins +' Euro!'            );        } else {            Alert.alert('Niet gekocht','Sorry, je hebt niet genoeg geld om deze energiebron te kopen.'            );        }    };    const sellItem = (item: IEnergyResource): void => {        if (item.amountOwned > 0) {            dispatch.energyResources.decreaseAmountOwned(dispatch.energyResources, item);            dispatch.coins.sell(dispatch.coins, item.price);            Alert.alert('Verkocht!','De energiebron '+ item.name +' is verkocht, '+'je hebt nu €'+ coins +' Euro.'            );        }  else {            Alert.alert('Niet verkocht','Sorry, de energiebron '+ item.name +' kon niet worden verkocht, '+'je hebt er geen in je bezit.'            );        }    };    return (<FlatList            style={styles.list}            data={energyResources.toArray()}            renderItem={                ({ item }) => <ProductComponent                    resource={item}                    onPurchase={purchaseItem}                    onSell={sellItem}                    canSell={item.amountOwned > 0}                />            }            keyExtractor={(item) => item.name}        />    );}

Both the purchase and sell methods are defined in the FlatList-component, and then passed to the individual elements (I figured this was better than defining the functions in ProductComponent itself and having each rendered item call on the state).

The ProductComponent component:

export interface IProductProps {    resource: IEnergyResource;    onPurchase: Function;    onSell: Function;    canSell: boolean;}const styles = StyleSheet.create({    buttonRight: {        alignItems: 'center',        alignSelf: 'flex-end',        backgroundColor: Constants.Colors.DodgerBlue,        marginVertical: 5,        padding: 10,        width: 150    },    image: {        alignSelf: 'flex-start',        height: 100,        width: 100    },    listItem: {        borderBottomColor: Constants.Colors.Blue,        borderBottomWidth: 2,        flex: 1,        flexDirection: 'row',        marginLeft: 5,        marginBottom: 0,        paddingBottom: 5    },    productInfo: {        width: 300,    },    rightButtons: {        alignItems: 'center',        alignSelf: 'flex-end'    },    sell: {        backgroundColor: Constants.Colors.Red    },    textLeft: {        alignSelf: 'flex-start',        fontSize: 20,    }});const ProductComponent: React.FC<IProductProps> = (props) => {    return (<View style={styles.listItem}><Image source={props.resource.image.image} width={50} height={50} style={styles.image} /><View style={styles.productInfo}><Text style={styles.textLeft}>{props.resource.name}</Text><Text style={styles.textLeft}>€{props.resource.price}</Text><Text style={styles.textLeft}>Energiewaarde: {props.resource.energyValue} Watt</Text><Text style={styles.textLeft}>In bezit: {props.resource.amountOwned}</Text></View><View style={styles.rightButtons}><TouchableHighlight style={styles.buttonRight} onPress={() => props.onPurchase(props.resource)}>                    {/* eslint-disable-next-line react-native/no-inline-styles */}<Text style={{ color: Constants.Colors.White, fontWeight: 'bold', fontSize: 15 }}>Kopen</Text></TouchableHighlight><TouchableHighlight style={[styles.buttonRight, styles.sell]} disabled={props.canSell} onPress={() => props.onSell(props.resource)}>                    {/* eslint-disable-next-line react-native/no-inline-styles */}<Text style={{ color: Constants.Colors.White, fontWeight: 'bold', fontSize: 15 }}>Verkopen</Text></TouchableHighlight></View></View>    );};

The methods are present in the IProductProps interface and the calls seem to work (I am getting the defined Alert as though I have indeed purchased a product). However, after clicking OK in the alertbox, the counter for the specified product (defined in ProductComponent as props.resource.amountOwned) remains 0 and I am unable to sell that same product.

These are the methods defined in the state models which I am calling:

/** * Increases the amount of items the player owns. * * @param {List<IEnergyResource>} state - the current state of the app * @param {IEnergyResource} item - the item which was bought * @returns {List<IEnergyResource>} state */function increaseAmountOwned(state: EnergyResourcesState, item: IEnergyResource): EnergyResourcesState {    const itemIndex = state.indexOf(item);    const newItem = {        amountOwned: item.amountOwned++,        ...item    };    return state.set(itemIndex, newItem);}/** * Decreases the amount of items the player owns. * * @param {List<IEnergyResource>} state - The current state of the app * @param {IEnergyResource} item - the item which was sold * @returns {List<IEnergyResource>} state */function decreaseAmountOwned(state: EnergyResourcesState, item: IEnergyResource): EnergyResourcesState {    const itemIndex = state.indexOf(item);    const newItem = {        amountOwned: item.amountOwned--,        ...item    } as IEnergyResource;    return state.set(itemIndex, newItem);}const initialState: IEnergyResource[] =    [        {            name:'Windmolen',            price: 15,            energyValue:20,            environmentValue:-15,            image:{                maxSize:{                    width:0.2,                    height:0.2,                },                image: images.windmill,            },            amountOwned: 0,            amountTotal: 30,            amountPlaced: 0,            location:{                x:0.05,                y:0            },        },{            name:'Watermolen',            price: 15,            energyValue:15,            environmentValue:-10,            image:{                maxSize:{                    width:0.2,                    height:0.2,                },                image: images.turbine            },            amountOwned: 0,            amountTotal: 30,            amountPlaced: 0,            location:{                x:0.05,                y:0.3            },        },{            name:'Zonnepaneel',            price: 15,            energyValue:10,            environmentValue:-5,            image:{                maxSize:{                    width:0.2,                    height:0.2,                },                image: images.solarPanel            },            amountOwned: 0,            amountTotal: 30,            amountPlaced: 0,            location:{                x:0.3,                y:0            },        }    ]const resources = {    state: List(initialState),    reducers: {        place:(state: EnergyResourcesState, name: string): EnergyResourcesState =>            state = doMutateEnergyResource(state, name, true),        remove:(state: EnergyResourcesState, name: string): EnergyResourcesState =>            state = doMutateEnergyResource(state, name, false),        increaseAmountOwned: increaseAmountOwned,        decreaseAmountOwned: decreaseAmountOwned    },};

I am using Rematch Redux framework to work with the state.

It is probably a minor detail I am overlooking here, so any help or nudges in the right direction is greatly appreciated.

Thank you in advance!


Viewing all articles
Browse latest Browse all 6213

Trending Articles



<script src="https://jsc.adskeeper.com/r/s/rssing.com.1596347.js" async> </script>