ignite-bowser icon indicating copy to clipboard operation
ignite-bowser copied to clipboard

Infinite rendering and infinite call to useEffect when checking store member length

Open anasjaghoub opened this issue 4 years ago • 1 comments

When trying to do conditional check on model number of elements infinite rendering happens, and useEffects keeps running forever.

Sample code , notice renderList code if uncomment the // if(categoryStore && categoryStore.categories.length > 0) {

then useEffects will keep calling to infinite.

import * as React from "react"
import { observer } from "mobx-react-lite"
import { FlatList, SafeAreaView, TextStyle, View, ViewStyle, Alert } from "react-native"
import { ParamListBase } from "@react-navigation/native"
import { NativeStackNavigationProp } from "react-native-screens/native-stack"
import { Screen, Text, Header } from "../components"
import { useStores } from "../models/root-store"
import { color } from "../theme"
import { useEffect, useState } from "react"

export interface CategoryScreenProps {
  navigation: NativeStackNavigationProp<ParamListBase>
}

const ROOT: ViewStyle = {
  backgroundColor: color.palette.offWhite,
}

const ITEM_VIEW: ViewStyle = {
  borderColor: color.palette.lightGrey,
  borderWidth: 3,
  padding: 20,
  marginVertical: 8,
  marginHorizontal: 16
}

const TITLE_TEXT: TextStyle = {
  fontSize: 32,
  color: color.palette.black,
  textAlign: "center"
}

export const CategoryScreen: React.FunctionComponent<CategoryScreenProps> = observer((props) => {
  const { categoryStore } = useStores()
  const fetchCategories = () => {
    categoryStore.getCategories()
  }
  const [refreshing, setRefreshing] = useState(false)
  useEffect(() => {
    setRefreshing(true)
    console.tron.log("before fetchCategories ", categoryStore.categories.length)
    fetchCategories()
    console.tron.log("after fetchCategories ", categoryStore.categories.length)
    setRefreshing(false)
  })

  const keyExtractor = item => String(item.id)

  const onPressItem = (item) => {
    props.navigation.navigate("list", {
      category: item
    })
  }

  const renderItem = ({ item }) => {
    const { id, name} = item
    return <View style={ITEM_VIEW}>
      <Text style={TITLE_TEXT} onPress={() => onPressItem(id)}>{name}</Text>
    </View>
  }

  const renderList = () => {
    // if(categoryStore && categoryStore.categories.length > 0) {

      return <FlatList
          data={categoryStore.categories}
          renderItem={renderItem}
          numColumns={1}
          keyExtractor={keyExtractor}
          onRefresh={fetchCategories}
          refreshing={refreshing}
        />
    // }
  }

  return (
    <View style={ROOT}>
      <View>
        <Text preset="header" tx="global.header" style={ { textAlign: "center", backgroundColor: "green", padding: 8 } } />
      </View>
      <SafeAreaView style={ { margin: 2 } }>
        {renderList()}
      </SafeAreaView>
    </View>
  )
})

Please advice what's the problem in this example?

anasjaghoub avatar May 08 '20 18:05 anasjaghoub

@jamonholmgren @robinheinze if possible to help me in this.

thanks in advance!

anasjaghoub avatar May 10 '20 06:05 anasjaghoub