Как придать отдельному элементу в массиве его собственное уникальное состояние с помощью React?

#javascript #reactjs #react-native #react-redux #react-hooks

#javascript #reactjs #react-native #react-redux #реагирующие хуки

Вопрос:

Я работаю через fullstackopen и выполняю упражнение 1.13. Я изо всех сил пытаюсь понять, как реализовать способ обновления состояния для отдельных элементов в массиве [анекдоты].

Каждому анекдоту разрешено определенное количество голосов.

Я могу увеличить количество голосов, но это увеличивает количество голосов для всех.

https://fullstackopen.com/en/part1/a_more_complex_state_debugging_react_apps#exercises-1-6-1-14

Приведенный ниже код — это то, что они предоставляют в качестве подсказки для реализации, а также некоторые подсказки об использовании arr.fill()

 const points = [1, 4, 6, 3]

const copy = [...points]
// increment the value in position 2 by one
copy[2]  = 1    

Цель: я хочу проголосовать за отображаемый случайный анекдот и сохранить этот результат, чтобы при следующем просмотре случайного анекдота он набрал то же количество голосов, что и ранее.

Мне удается реализовать функциональность кнопки для увеличения голосов на единицу, но это приводит только к тому, что все анекдоты набирают одинаковое количество голосов.

Как будет выглядеть структура данных? Как бы вы обновили состояние в ситуации, связанной со сложными структурами данных?

Ниже приведен мой код:

 const App = () => {
  const anecdotes = [
    'If it hurts, do it more often',
    'Adding manpower to a late software project makes it later!',
    'The first 90 percent of the code accounts for the first 90 percent of the development time...The remaining 10 percent of the code accounts for the other 90 percent of the development time.',
    'Any fool can write code that a computer can understand. Good programmers write code that humans can understand.',
    'Premature optimization is the root of all evil.',
    'Debugging is twice as hard as writing the code in the first place. Therefore, if you write the code as cleverly as possible, you are, by definition, not smart enough to debug it.'
  ]

  const votings = [0, 0, 0, 0, 0, 0]
  let copy = [...votings]

  
  const handleVotes = () => {
    setVotes(votes   1)
    console.log(votings)
    votings[selected] = votings[selected]   votes
    console.log(votings)
    copy = [...votings]
    return copy
  }
   
  const [selected, setSelected] = useState(0)
  const [votes, setVotes] = useState(0)

  const getRandomAnecdote = () => {
    let randomVal = Math.floor(Math.random(selected) * anecdotes.length)
    setSelected(randomVal)
    console.log(randomVal)
  }


  return (
    <div>
      {anecdotes[selected]}
      <br></br>
      {votings[selected]}
      <br/> 
      <p>This anecdote has: {copy[selected]} votes</p>
      <button onClick={getRandomAnecdote}>Random</button>
      <button onClick={handleVotes}>Vote</button>
    </div>
  )
} 
 <script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.6.3/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.6.3/umd/react-dom.production.min.js"></script> 

Редактировать:

ВОТ РАБОЧИЙ КОД БЛАГОДАРЯ ОТВЕТУ КРИСТИАНА НИЖЕ:

 import React, { useState } from 'react'

const App = () => {
  const anecdotes = [
    'If it hurts, do it more often',
    'Adding manpower to a late software project makes it later!',
    'The first 90 percent of the code accounts for the first 90 percent of the development time...The remaining 10 percent of the code accounts for the other 90 percent of the development time.',
    'Any fool can write code that a computer can understand. Good programmers write code that humans can understand.',
    'Premature optimization is the root of all evil.',
    'Debugging is twice as hard as writing the code in the first place. Therefore, if you write the code as cleverly as possible, you are, by definition, not smart enough to debug it.'
  ]

  const handleVotes = () => {
    const votesCopy = [...votes]
    votesCopy[selected]  = 1
    setVotes(votesCopy)
  }

  const [selected, setSelected] = useState(0)
  const [votes, setVotes] = useState([0, 0, 0, 0, 0, 0])

  const getRandomAnecdote = () => {
    let randomVal = Math.floor(Math.random(selected) * anecdotes.length)
    setSelected(randomVal)
    console.log(randomVal)
  }

  return (
    <div>
      {anecdotes[selected]}
      <br/> 
      <p>This anecdote has: {votes[selected]} votes</p>
      <button onClick={getRandomAnecdote}>Random</button>
      <button onClick={handleVotes}>Vote</button>
    </div>
  )
}

export default App; 
 <script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.6.3/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.6.3/umd/react-dom.production.min.js"></script> 

Комментарии:

1. Сохранение данных в виде массива — это нормально. Вероятно, вы делаете что-то не так при увеличении голосов. Поэтому, пока вы не покажете нам эту часть, трудно сказать вам, что не так.

2. Хорошо, я только что обновил сообщение своим кодом.

3. Так что мне нужно будет изменить const [votes, setVotes] на useState([]) ?

Ответ №1:

Итак, проблема в том, что вы инициализируете состояние (голоса) с помощью 0. Вместо этого вы должны инициализировать его массивом нулей.

 //votes[i] represents the number of votes for the i-th anecdote
const [votes, setVotes] = useState([0,0,0,0,0,0])
 

Теперь, когда вы обрабатываете голосование:

  const handleVotes = () => {
    //you make a copy of the votes
    const votesCopy = [...votes]
    
    //then increase the votes for the selected anecdote
    votesCopy[selected]  = 1;
    
    //and finally update the state
    setVotes(votesCopy);
  }