In my Nextjs web application, one of my pages has two functions that allow for emails to be added or removed from an array using nextjs's useState().
const [invites, setInvites] = useState([])
// other code
const lmao = () => {
console.log(invites)
}
const addEmail = async (email) => {
if(!invites.includes(email)) {
setInvites([...invites, email])
}
lmao()
}
const removeEmail = async (email) => {
let tempArray = invites
const index = tempArray.indexOf(email)
if(index > -1) {
tempArray.splice(index, 1)
}
setInvites(tempArray)
lmao()
}
The function addEmail successfully results in a component rerender, and when ran, will visibly update the page with the added email. However, the function removeEmail fails to rerender the page. I used the function lmao() to see that invites was indeed being changed as needed, the page just was not rerendering to display the change.
I have also looked at Why does setState([...arr]) cause a rerender but setState(arr) does not?, and it does not answer my question because in my case, the item passed into the mutator is not === to its previous value, unless I am missing something. If the linked question does explain my problem, could someone elaborate further on why setInvites(tempArray) does not cause a rerender even though it changes the state value, and how I would change my code to do so?
I suppose that tempArray is still the same array, that is, the same reference. I would put setInvites([...tempArray]) instead of setInvites(tempArray) in removeEmail
tempArray is another reference to the same array, i.e. it is ===
let foo = ['a', 1, 'b']
let bar = foo
bar.splice(1, 1)
console.log(foo, bar, foo===bar) // [ 'a', 'b' ] [ 'a', 'b' ] true
You can either clone your array:
let bar = [...foo]
Or use some sort of removal that does not mutate the original array:
let bar = foo.filter(f => f !== 1)
In both cases you'll get
console.log(foo, bar, foo===bar) // [ 'a', 1, 'b' ] [ 'a', 'b' ] false