0

I have an event handler which calculates the most voted phrase and prints it every time voting is done. However, after my first vote, my code always gives the last phrase of the array instead of the most voted one. It works after the first vote perfectly. What have I done wrong in my code?

const App = props => {
const [selected, setSelected] = useState(0);
let [votes, setVotes] = useState([0, 0, 0, 0, 0, 0]);
let [mostVotes, setMostVotes] = useState(0);

 const handleVote = () => {
 let newArray = [...votes];
 newArray[selected] += 1;
 setVotes(newArray);

 let array = new Array(...votes);
 let i = Math.max(...array);
 for (var a = 0; a < array.length; a++) {
  if (votes[a] === i) setMostVotes(a);
   }
  };

return (
<div>
  <h2>Anecdote of the day</h2>
  <div>{props.anecdotes[selected]} </div>
  <div>has {votes[selected]} votes</div>
  <div>
    <Button onClick={handleVote} text="vote" />
    <Button onClick={randomAnecdote} text="next anecdote" />
  </div>
     {console.log(mostVotes)}
     <h2>Anecdote with the most votes</h2>
     <p>{anecdotes[mostVotes]}</p>

  </div>
 );
 };


 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."
  ];
5
  • Can you reveal a bit more about that useState function? It would help a lot in debugging. Commented Sep 2, 2019 at 12:40
  • It is a way of using State hooks, same as this.state.voted or this.setState as in the documents for Using the State Hook for React. Commented Sep 2, 2019 at 12:44
  • 1
    It would be helpful if you can create a codepen or sandbox link Commented Sep 2, 2019 at 12:45
  • Also can you can randomAnecdote function definition ? Commented Sep 2, 2019 at 12:50
  • codesandbox.io/embed/cool-shape-1leeq Commented Sep 2, 2019 at 12:52

2 Answers 2

2

There is something you should know about useState. When the state changes, the component is re-rendered with the new values.

What is happening here is that votes did not change after setVotes, because you're still executing the old state.

setVotes(newArray);
let array = new Array(...votes); // votes did not change here

For this reason, you should avoid using state variables when you don't need them.

One solution (maybe not the best, but will help you better understand states) would be:

 let [votes, setVotes] = useState([0, 0, 0, 0, 0, 0]);
 let mostVotes = 0;

 //This is executed every time the component is re-rendered
 let array = new Array(...votes);
 let i = Math.max(...array);
 for (var a = 0; a < array.length; a++) {
  if (votes[a] === i) {mostVotes = a};
 }

 const handleVote = () => {
   let newArray = [...votes];
   newArray[selected] += 1;
   setVotes(newArray); //This triggers a re-render
 };


Sign up to request clarification or add additional context in comments.

1 Comment

Thanks, this is what I wanted to do. I will try to use state only when needed now, this was good knowledge.
0

You should replace this line let array = new Array(...votes); with this let array = new Array(...newArray);. The variable votes holds the previous state. When you use it the condition if (votes[a] === i) will evaluate to true for all objects, as they all 0 at the beginning.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.