skip to Main Content

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.

2

Answers


  1. It looks like object being passed as extraData is a boolean. This means that if the previous value was true, setting it as true again wouldn’t count as a change. Instead use an object and update it when you want list to update.

    To try just set extraData={{}}. if everything works as expected it means that your update logic has some problem.

    Login or Signup to reply.
  2. @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.

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search