-1

I'm new at React and trying to create a scoreboard app which has the following state:

state = {
    home_team: [
      {
        id: 1,
        name: "Jobe Watson",
        goals: 0,
        behinds: 0,
      },
      {
        id: 2,
        name: "James Hird",
        goals: 0,
        behinds: 0,
      },
      {
        id: 3,
        name: "Steven Alessio",
        goals: 0,
        behinds: 0,
      },
      {
        id: 4,
        name: "Che Cockatoo-Collins",
        goals: 0,
        behinds: 0,
      }
    ],
    away_team: [
      {
        id: 1,
        name: "Chris Judd",
        goals: 0,
        behinds: 0,
      },
      {
        id: 2,
        name: "Anthony Koudafidis",
        goals: 0,
        behinds: 0,
      },
      {
        id: 3,
        name: "Steven Silvagni",
        goals: 0,
        behinds: 0,
      },
      {
        id: 4,
        name: "Brendan Fevola",
        goals: 0,
        behinds: 0,
      },
    ]
  }

I am trying to run a score change function as below:

addScore = (i, delta, team, score) => {
    const val = eval(`this.state.${team}[${i}].${score} += ${delta}`)
    console.log(val)
    this.setState( {
        [score]: val
    })
  }

where it is called in the Counter component as follows:

onClick={()=>addScore(index, +1, team, 'goals')

In this case, "index" refers to the player index in either team array, and "team" refers to either "home_team" or "away_team".

The only way I seem to be able to dynamically add the information into the setState method seems to be through a template literal into eval() then calling it in setState.

Knowing there are problems with eval() - are there any other ways to do this? I have tried using new Function()() without success.

Can anyone offer another solution? Thanks in advance.

Tom Madsen
  • 13
  • 1
  • Just clone your value, edit and set your state – Quentin Grisel May 18 '20 at 02:24
  • Does this answer your question? [Whats the best way to update an object in an array in ReactJS?](https://stackoverflow.com/questions/28121272/whats-the-best-way-to-update-an-object-in-an-array-in-reactjs) – Emile Bergeron May 18 '20 at 02:26
  • 1
    ``eval(`this.state.${team}[${i}].${score} += ${delta}`)`` This mutates the state, [don't mutate the state.](https://stackoverflow.com/q/37755997/1218980) – Emile Bergeron May 18 '20 at 02:29
  • 1
    Also, [`eval` is _evil_.](https://stackoverflow.com/q/197769/1218980) – Emile Bergeron May 18 '20 at 02:31
  • using index instead of a produced identifier will make it difficult to edit. For example, Each new result even if you want it displayed at the top of a list will be placed at the bottom in react. – Alexander Hemming May 18 '20 at 02:48

1 Answers1

1

I think you are bit confused on how to get access value via all available variables, here you go simple way :

// this.state.${team}[${i}].${score}

this.state[team][i][score]

Second you are mutating state, that you shouldn't, you can update state this like :

addScore = (i, delta, team, score) => {
    const updated = this.state[team].map((el,index) => {
        if(i=== index) {
            const score = el.score + delta;
            el = { ...el , score }
        }
        return el
    })

    this.setState((state) => {
        ...state ,
        [team] : updated
    })
}
Vivek Doshi
  • 56,649
  • 12
  • 110
  • 122
  • Vivek - thanks so much - every other suggest just didn't cut it, but I used you suggestion with the following edit which solved my problem!! ```addScore = (i, delta, team, score) => { const updated = this.state[team].map((el,index) => { if(i=== index) { el[score] += delta; el = { ...el , score } } return el }) this.setState((prevState) => { return { ...prevState , [team] : updated } }) } ``` – Tom Madsen May 18 '20 at 04:49