Follow

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use
Contact

How to update state in an if statement contained in a map

I’m mapping an object and depending on the value of the currently mapped object (either 1 or greater than 1) it will go to it’s respective If function.

I’m trying to update state to know how many object elements are matching the given requirements.

const displayMovements = () => {
  return(
    movements.map((m) => {
      if (m.value === 1) {
        setAmountEqualToOne(amountEqualToOne + 1)
        return(
          <DisplayTemplateOne prop={m}/>
        )
      } else if (m.value > 1) {
        setAmountGreaterThanOne(amountGreaterThanOne + 1)
          return(
            <DisplayTemplateTwo prop={m}/>
          )
      }
    })
  )
}

I’m running into an infinite loop error and am unsure of where to go next.

MEDevel.com: Open-source for Healthcare and Education

Collecting and validating open-source software for healthcare, education, enterprise, development, medical imaging, medical records, and digital pathology.

Visit Medevel

>Solution :

Essentially the problem here is that you’re updating state when rendering. And updating state triggers a re-render. So the cycle is:

  • Render the component
  • Which updates the state
  • Which re-renders the component
  • Which updates the state
  • and so on…

(As an aside, the state updates were broken too. State updates are asynchronous, so these were being queued up and ultimately only the last one will be made here. Don’t update state in a loop, instead calculate the new state and update it once after the loop. But that’s a separate issue.)

So, fundamentally, don’t update state on every render. But then the question becomes, why are you trying to? What’s the goal?

I’m trying to update state to know how many object elements are matching the given requirements.

Don’t store that in state. That’s a value that’s calculated from state, not stored in state. And you can calculate that trivially when rendering the component. Something like this:

const amountEqualToOne = movements.filter(m => m.value === 1).length;
const amountGreaterThanOne = movements.filter(m => m.value > 1).length;

return(
  movements.map(m => 
    m.value === 1 ? <DisplayTemplateOne prop={m}/> :
    m.value > 1 ? <DisplayTemplateTwo prop={m}/> :
    null)
);

The above also corrects a potential issue where the callback passed to .map() wasn’t always returning a value. In this case it will at least explicitly return null as a default case, instead of undefined.

But in this case wherever you intend to use amountEqualToOne and amountGreaterThanOne, they’re re-calculated on every render and are available to be used.

Storing calculated values in state effectively means storing the same information twice in two different state values, and needing to manually keep those values synchronized. Which is a whole lot of trouble you don’t really want.

Add a comment

Leave a Reply

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use

Discover more from Dev solutions

Subscribe now to keep reading and get access to the full archive.

Continue reading