Home > database >  weird problem. adding 1 to 0 doesnt do anything
weird problem. adding 1 to 0 doesnt do anything

Time:04-28

1Okay, i dont even know how to describe this problem but i will try my best. you can find all my code at the bottom

 const scores = { 0: 0, 1: 0, 2: 0, 3: 0, 4:0, 5:0, 6:0 }
 const [point, setPoint] = useState(scores)

so i setstate to an array, later on i am calling it with a button

 <button onClick ={()=> setPoint (point[selected]  1 )}>Vote</button>
 <button onClick={()=> setSelected(Math.floor(Math.random()* anecdotes.length ))}>next anecdotes</button>
 {scores[selected]}

at first it should the value at the [selected] to be at 0, but whenever i press on the vote button and add 1, it is still 0. i just wonder if anyone can help with this.

import { 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 10 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.',
    'Programming without an extremely heavy use of console.log is same as if a doctor would refuse to use x-rays or blood tests when diagnosing patients'
  ]
   
  const [selected, setSelected] = useState(0) 
  const scores = { 0: 0, 1: 0, 2: 0, 3: 0, 4:0, 5:0, 6:0 }
  const [point, setPoint] = useState(scores)
  
  return (
    console.log (selected),
    console.log (point[selected]),
    <div>
      {anecdotes[selected]}
      <br></br>
      <button onClick ={()=> setPoint (point[selected]  1 )}>Vote</button>
      <button onClick={()=> setSelected(Math.floor(Math.random()* anecdotes.length ))}>next anecdotes</button>
      {point[selected]}

    </div>
  )
}
/*onst Set = (...[points, selected]) => {
  points [selected]  = 1;
  console.log(points [selected]);
<h1>{points}</h1>
}*/

export default App

CodePudding user response:

I think setPoint (point[selected] 1 ) is replacing your state with a number, instead of updating the object (which was the initial state of scores). I think you may need to do something like ...

   const updatedValue = point[selected]   1;
   setPoint({...point, [selected]: updatedValue})

CodePudding user response:

You cannot update state like that if the variable is an object. You should access the most recent previous state snapshot using the updater function, then update the variable, and return the new state.

setPoint(state => {
  
  return { ...state, [selected]: state[selected]   1 }

})

or

setPoint(state => {
  
  state[selected]  

  return state

})

Using the updater function ensures you access the most recent state snapshot. Simply using setPoints({ ...points, [selected]: points[selected] 1 })} does not guarantee the most recent state will be accessed.

CodePudding user response:

Update the logic for updating the points state as shown below:

const anecdotes = [
  "If it hurts, do it more often",
  "Adding manpower to a late software project makes it later!",
  "Premature optimization is the root of all evil.",
];

const App = () => {
  const [selected, setSelected] = React.useState(0);
  const [points, setPoints] = React.useState({ 0: 0, 1: 0, 2: 0, 3: 0, 4: 0, 5: 0, 6: 0 });

  return (
    <div>
      {anecdotes[selected]}
      <br></br>
      <button onClick={() => setPoints({ ...points, [selected]: points[selected]   1 })}>
        Vote
      </button>
      <button onClick={() => setSelected(Math.floor(Math.random() * anecdotes.length))}>
        Next Anecdote
      </button>
      {points[selected]}
    </div>
  );
};

ReactDOM.render(<App />, document.getElementById("root"));
<script crossorigin src="https://unpkg.com/react@17/umd/react.development.js"></script>
<script crossorigin src="https://unpkg.com/react-dom@17/umd/react-dom.development.js"></script>
<div id="root"></div>

Also, there's no need for a separate scores variable and you can also move the anecdotes array outside the component.

Note: I've reduced the no. of anecdotes so that you can quickly see the votes working.

Bonus Tip:

Currently your random selection can pick up the same anecdote that is currently selected, which means nothing happens on that button click, which is not a very good user experience.

Checkout the snippet below where every time you click on the "Next Anecdote" button, it guarantees a new anecdote.

const anecdotes = [
  "If it hurts, do it more often",
  "Adding manpower to a late software project makes it later!",
  "Premature optimization is the root of all evil.",
];

const App = () => {
  const [selected, setSelected] = React.useState(0);
  const [points, setPoints] = React.useState({ 0: 0, 1: 0, 2: 0, 3: 0, 4: 0, 5: 0, 6: 0 });

  const getNextAnecdote = () => {
    const choosableIndicies = anecdotes.map((_, i) => i).filter((i) => i !== selected);
    setSelected(choosableIndicies[Math.floor(Math.random() * choosableIndicies.length)]);
  };

  return (
    <div>
      {anecdotes[selected]}
      <br></br>
      <button onClick={() => setPoints({ ...points, [selected]: points[selected]   1 })}>
        Vote
      </button>
      <button onClick={getNextAnecdote}>Next Anecdote</button>
      {points[selected]}
    </div>
  );
};

ReactDOM.render(<App />, document.getElementById("root"));
<script crossorigin src="https://unpkg.com/react@17/umd/react.development.js"></script>
<script crossorigin src="https://unpkg.com/react-dom@17/umd/react-dom.development.js"></script>
<div id="root"></div>

  • Related