2

I am learning and practicing hooks useState in react js. For example, when declaring a state variable like this,

const [votes, setVotes] = useState(0) 

I know that the 0 value in useState() means that votes is initialized with starting value of 0. However, advancing a little bit, like this,

const [votes, setVotes] = useState(() => Array(fruits.length).fill(0)) 

Given an array,

const fruits = ["kiwi", "banana", "mango", "apple", "durian"] 

I am a little confused with the Array in the second state variable wrapping fruits.length, why do we have to wrap it with Array ? fruits is already an array. And just to make sure that I understand, the .fill(0) means that we will initialize every element in the array fruit with 0? Am I right ? To give a context, I have an array fruits and two buttons, one is to vote, and the other is to select randomly the next fruit. Every time I vote, the vote will increase and when I click the other button, random fruits will be displayed and the vote will be 0 for fruits that haven't got voted. This is the vote button code,

const handleVotes = () => { setVotes((votes) => votes.map((vote, index) => index === selected ? vote + 1 : vote) ) } 
1
  • if you do fruits.fill(0) it will overwrite all values in fruits with 0 for each value. Array(fruits.length).fill(0) makes a new array filled with 0s, matching the length of fruits. run it in a console to see for yourself. also note () => ... precedes the state, this is a lazy state initializer and runs only once when the component is initialized. this is important otherwise Array(fruits.length).fill(0) would be evaluated during each render, even though the value would be discarded. Commented Feb 11, 2023 at 3:44

2 Answers 2

2

Mapping over the entire array of fruits is rather inefficient. We can use a Map which allows us to create a mapping between fruits and their votes. This allows us to update a fruit directly, without having to evaluate a condition against each element. Run the demo below and vote for your favourite!

function App({ fruits }) { const [selected, setSelected] = React.useState(fruits[0]) const [votes, setVotes] = React.useState(() => new Map) const select = fruit => event => { setSelected(fruit) } const vote = event => { setVotes(vs => new Map(vs).set(selected, (vs.get(selected) || 0) + 1) ) } return <div> {fruits.map(f => <button onClick={select(f)} className={selected == f ? "selected" : ""} children={f} /> )} <button onClick={vote} children="vote" /> <pre>{JSON.stringify(Object.fromEntries([...votes]))}</pre> </div> } ReactDOM.render(<App fruits={["🥝","🍎","🍑"]} />, document.body)
.selected { border-color: teal; }
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.13.0/umd/react.production.min.js"></script> <script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.13.0/umd/react-dom.production.min.js"></script>

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

Comments

1

Array(array.length).fill(0) is a JavaScript expression that creates a new array filled with a specified value. The expression creates an array with the length equal to the length of the array variable passed as an argument. The .fill(0) method is then used to fill the entire array with the value 0.

Here's an example:

const array = [1, 2, 3, 4, 5]; const newArray = Array(array.length).fill(0); console.log(newArray); // Output: [0, 0, 0, 0, 0] 

In this example, array is an array with 5 elements, so Array(array.length).fill(0) creates a new array with 5 elements, all filled with the value 0.

I hope this helps!

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.