I am populating an array with dummy data and once it is done, using useEffect, i'm trying to delete the the element on first index and update it on the DOM. The array is being updated on console but the changes doesn't reflect on DOM.
import './App.css';
import { useState,useEffect } from 'react';
import {faker} from '@faker-js/faker'
function App() {
var catsarray = []
const [cats, changecat] = useState(()=>{
for (let index = 0; index < 10; index ) {
catsarray.push(faker.animal.cetacean())
}
return catsarray
})
useEffect(()=>{
},[cats])
const removecat = () => {
cats.shift()
changecat(cats)
}
return (
<div className="App">
<h1> List of cats </h1>
<div className='wrapper'>
<ul>
<>
{catsarray.length > 2 ?
cats.map((title, index)=>(
<li key={index}> {index} : {title} </li>
)) : 'Array is empty' }
</>
</ul>
</div>
<button title='button' onClick={removecat}> Click me </button>
</div>
);
}
export default App;
CodePudding user response:
The reason is like @Jacob Smit said:
React uses referential comparisons to determine whether or not a value has changed. If you mutate (change) the state and provide it back to the setState function react sees the same value as it already has stored and thinks there is no operation to be carried out
So you need to use a different refernece when mutating a state
for example
// assign a new array
let tempCats = [...cats]
// operate this new array
tempCats.shift()
// set the new array to state
changecat(tempCats)
Or like @Jacob Smit's suggestion
changecat(cats => cats.filter((_, i) => i !== 0))
a example from your question with a little modify
import React from "react"
import { useState, useEffect } from 'react';
function App() {
var faker = ["steve", "john", "cat", "dog", "alex", "big"]
var catsarray = []
const [cats, changecat] = useState(() => {
for (let index = 0; index < faker.length; index ) {
catsarray.push(faker[index])
}
return catsarray
})
useEffect(() => {
}, [cats])
const removecat = () => {
let tempCats = [...cats]
tempCats.shift()
console.log(tempCats)
changecat(tempCats)
// or @Jacob Smit's suggestion
//changecat(cats => cats.filter((_, i) => i !== 0))
}
return (
<div>
<h1> List of cats </h1>
<div>
<ul>
<>
{cats.length > 2 ?
cats.map((title, index) => (
<li key={index}> {index} : {title} </li>
)) : 'Array is empty'}
</>
</ul>
</div>
<button title='button' onClick={removecat}> Click me </button>
</div>
);
}
export default App;
a code snippet display
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/18.2.0/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/18.2.0/umd/react-dom.production.min.js"></script>
<script src="https://unpkg.com/babel-standalone@6/babel.min.js"></script>
<div id="root"></div>
<script type="text/babel">
function App() {
var faker = ["steve", "john", "cat", "dog", "alex", "big"]
var catsarray = []
const [cats, changecat] = React.useState(() => {
for (let index = 0; index < faker.length; index ) {
catsarray.push(faker[index])
}
return catsarray
})
React.useEffect(() => {
}, [cats])
const removecat = () => {
let tempCats = [...cats]
tempCats.shift()
console.log(tempCats)
changecat(cats => cats.filter((_, i) => i !== 0))
}
return (
<div>
<h1> List of cats </h1>
<div>
<ul>
{cats.length > 2 ?
cats.map((title, index) => (
<li key={index}> {index} : {title} </li>
)) : 'Array is empty'}
</ul>
</div>
<button title='button' onClick={removecat}> Click me </button>
</div>
);
}
</script>
<script type="text/babel">
ReactDOM.render(
<App></App>
, document.getElementById("root"));
</script>