Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

React Native + Context + FlashList wont re-render with Context update + extraData updating

The problem: I have a FlashList that uses React Context to fill in the data (the data is an array of objects that renders a View) but when I update the context and the extraData prop for FlashList, the list does not re-render, or re-renders sometimes, or takes multiple events to actually re-render.

The Code:

// Many imports, they are all fine though

export default () => {
  // Relevant context.
  const {
    cardsArray,
    cardsArrayFiltered,
    updateCardsArray,
    updateCardsArrayFiltered
  } = useContext(AppContext);
  
  // Relevant state.
  const [didUpdateCards, setDidUpdateCards] = useState(false);
  const [cardsFilters, setCardsFilters] = useState([]);

  // Relevant refs.
  const flatListRef = useRef(null);
  
  // Example effect on mount
  useEffect(() => {
    setInitialAppState();
  }, []);
  
  // Effect that listen to changing on some data that update the context again
  useEffect(() => {
      const newCardsArray = doSomeFiltering(cardsArray, cardsFilters);
  
      updateCardsArrayFiltered(newCardsArray);
      setDidUpdateCards(!didUpdateCards);
  }, [cardsFilters]);
  
  // Example of promisey function that sets the initial context.
  const setInitialAppState = async () => {
    try {
      const newCardsArray = await getPromiseyCards();
  
      updateCardsArrayFiltered(newCardsArray);
      updateCardsArray(newCardsArray);
    } catch ( err ) {
      console.debug( err );
    }
  }
  
  // Renderer for the list item.
  const renderListItem = useCallback((list) => <Card key={list.index} card={list.item} />, []);
  
  // List key extractor.
  const listKeyExtractor = useCallback((item) => item.id, []);
  
  return (
    <FlashList
      ref={flatListRef}
      data={cardsArrayFiltered}
      extraData={didUpdateCards}
      keyExtractor={listKeyExtractor}
      renderItem={renderListItem}
      showsVerticalScrollIndicator={false}
      estimatedItemSize={Layout.window.height}
    />
  );
}

Notes:

  • What I did not write all out is the function, logic, view to update cardsFilters however the above effect IS running when it changes.
  • Moreover, this line here, const newCardsArray = doSomeFiltering(cardsArray, cardsFilters); does indeed return the proper updated data.

What's going on here? I am updating the extraData prop with that didUpdateCards state when the context changes which I thought was the requirement to re-render a FlatList/FlashList.

like image 782
Staghouse Avatar asked Oct 27 '25 02:10

Staghouse


1 Answers

@Staghouse your component contains key property, and official docs recommend to remove it: https://shopify.github.io/flash-list/docs/fundamentals/performant-components/#remove-key-prop :

"Using key prop inside your item and item's nested components will highly degrade performance.

Make sure your item components and their nested components don't have a key prop. Using this prop will lead to FlashList not being able to recycle views, losing all the benefits of using it over FlatList."

Hope this helps.

like image 59
Nik Handyman Avatar answered Oct 29 '25 19:10

Nik Handyman



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!