react-nativereact-native-flatlistflatlist

React Native Component Not Updating State


I have the unshakable feeling that I am doing something stupidly wrong!

I am working on an e-commerce app and I am facing an issue with nested <FlatList />

The screen isn't rendering after state change, can someone tell me what I am doing wrong

import {useState} from 'react';
import {FlatList} from 'react-native';
import {IconButton, PaperProvider, Text} from 'react-native-paper';

const data = [
  [
    {id: '0', value: 'size-s'},
    {id: '1', value: 'size-m'},
    {id: '2', value: 'size-l'},
  ],
  [
    {id: '0', value: 'ab-testing'},
    {id: '1', value: 'access-point'},
    {id: '2', value: 'account'},
  ],
];

export default () => {
  const [variant, variantSet] = useState([
    {id: '0', value: 'size-s'},
    {id: '2', value: 'account'},
  ]);
  console.log(variant);

  return (
    <PaperProvider>
      <Text>Working</Text>
      {data.map((current, i) => (
        <FlatList
          horizontal
          contentContainerStyle={{flex: 1, justifyContent: 'center'}}
          legacyImplementation={false}
          key={i}
          data={current}
          renderItem={({item}) => (
            <IconButton
              icon={item.value}
              style={{
                backgroundColor: variant[i]?.id === item.id ? 'red' : null,
              }}
              onPress={() => {
                console.log('Pressed', variant);
                let newVariant = variant;
                newVariant[i] = item;
                variantSet(newVariant);
              }}
            />
          )}
        />
      ))}
    </PaperProvider>
  );
};


Solution

  • You are actually mutating the state directly which can lead to unexpected behavior in React. React relies on immutable state updates to trigger re-renders. To fix this issue you should create a copy of the state before making changes and then update the state with the copy

    like this

    import React, { useState } from 'react';
    import { FlatList } from 'react-native';
    import { IconButton, PaperProvider, Text } from 'react-native-paper';
    
    const data = [
      [
        { id: '0', value: 'size-s' },
        { id: '1', value: 'size-m' },
        { id: '2', value: 'size-l' },
      ],
      [
        { id: '0', value: 'ab-testing' },
        { id: '1', value: 'access-point' },
        { id: '2', value: 'account' },
      ],
    ];
    
    export default () => {
      const [variant, setVariant] = useState([
        { id: '0', value: 'size-s' },
        { id: '2', value: 'account' },
      ]);
    
      return (
        <PaperProvider>
          <Text>Working</Text>
          {data.map((current, i) => (
            <FlatList
              horizontal
              contentContainerStyle={{ flex: 1, justifyContent: 'center' }}
              legacyImplementation={false}
              key={i}
              data={current}
              renderItem={({ item }) => (
                <IconButton
                  icon={item.value}
                  style={{
                    backgroundColor: variant[i]?.id === item.id ? 'red' : null,
                  }}
                  onPress={() => {
                    console.log('Pressed', variant);
                    const newVariant = [...variant]; // Create a copy of the state
                    newVariant[i] = item;
                    setVariant(newVariant); // Update the state with the copy
                  }}
                />
              )}
            />
          ))}
        </PaperProvider>
      );
    };