useMemo on useState with Array and many Object

4.9k views Asked by At

My apps run although its kind of slow since I loop to create button and loop again to change the color of the button

Its slow because every time I change a color in a button I have to loop in useState array of objects

My question is, how do I only render one object in an Array that uses useState ? Or.. is there any faster way / better way than looping like this ?

I also try to target the checked status with booleanMonth[0].checked=true which change the status without looping but it doesn't change the color.

this is the array:

  const [booleanMonth,setMonth]=useState([
    {key:0,value:'January',title:'Jan',color:'black',checked:false},
    {key:1,value:'February',title:'Feb',color:'black',checked:false},
    {key:2,value:'March',title:'Mar',color:'black',checked:false},
    {key:3,value:'April',title:'Apr',color:'black',checked:false},
    {key:4,value:'May',title:'May',color:'black',checked:false},
    {key:5,value:'June',title:'Jun',color:'black',checked:false},
    {key:6,value:'July',title:'Jul',color:'black',checked:false},
    {key:7,value:'August',title:'Aug',color:'black',checked:false},
    {key:8,value:'September',title:'Sep',color:'black',checked:false},
    {key:9,value:'October',title:'Oct',color:'black',checked:false},
    {key:10,value:'November',title:'Nov',color:'black',checked:false},
    {key:11,value:'December',title:'Dec',color:'black',checked:false}
    ])

this is where I create buttons which will loop if one of the object in array ABOVE changed because I pressed a button :

 const createButtonMonth = useMemo(() =>{
    console.log('createButtonMonth')
    return (<View style={styles.containerForButtons2}>
            {
              booleanMonth.map((item,key) => 
                <View key={item.key} style={styles.buttonFilter3}>
                <Button style={styles.buttonFilter3}
                title={item.title} 
                value={item.checked} 
                onCheckColor='red'
                color={item.checked==true ? 'green':'black'}
                onPress={()=>onPressMonthFilter(booleanMonth[item.key].key,booleanMonth[item.key].checked)}
                /></View>)
            }
            </View>)
  },[booleanMonth])

this is the press button function which also loop to determine which button to change its color because its checked status true / false (I think this slows me down also because of the loop)

  const onPressMonthFilter = (keyMonth,statusMonth) =>{
    let newArr = [...booleanMonth]
    if(newArr[keyMonth].checked==false){
      newArr[keyMonth].checked=true
    }else{
      newArr[keyMonth].checked=false
    }
    
    setMonth(newArr)
  }

open for any suggestion :< help newbie here please

2

There are 2 answers

0
I am L On

The only thing I can think of to further enhance this is to wrap onPressMonthFilter with useCallback

 const onPressMonthFilter = useCallback((keyMonth,statusMonth) =>{
    let newArr = [...booleanMonth]
    if(newArr[keyMonth].checked==false){
      newArr[keyMonth].checked=true
    }else{
      newArr[keyMonth].checked=false
    }
    
    setMonth(newArr)
  }, [setMonth, booleanMonth])

So the function will return a memoized value. Other than that the code seems to be pretty straight forward, and you don't really have any choice but to loop them to assign the UI.

looping on the array that small shouldn't slow down the app tho, unless you have thousands of data on the array.

2
Pablo On

I suggest keeping the static data static and only the application state in the state. From a record perspective I know it makes sense to have all the attributes for an entity together but it but in this case I think you can just manage the state of the buttons and infer everything else. For instance, you can infer the color of the button if you know whether it is checked or not.

You can have a list of months as an static array to generate your UI. Then keep array state to keep track of buttons that are checked. If the value in the button is present in the state then button should be checked. If the button is checked then the color should be green. The action of the button will simply add its value to the state array if missing or remove it if exists.

Please review this example showcasing the suggestions https://codesandbox.io/s/elated-bose-0vwtw