1

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?

Ryan Millares
  • 525
  • 4
  • 16

2 Answers2

1

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

MrCano369x
  • 328
  • 3
  • 6
  • I will try this out, thanks for the suggestion – Ryan Millares Dec 09 '21 at 01:32
  • It successfully makes the component re-render, but it is for some reason displaying different information than the actual array (i.e) The array has item 1 and 2. If I delete item 2, Item 2 disappears. However, if I instead delete item 1, item 2 still disappears leaving item 1, but console.log() shows item 2 is the only item in array – Ryan Millares Dec 09 '21 at 07:10
  • Care to share the modified code that you have? Also keep in mind that [setting state is an async operation](https://stackoverflow.com/questions/38558200/react-setstate-not-updating-immediately), logging `invites` right after the `setInvites()` call will not output the updated value. – juliomalves Dec 09 '21 at 18:07
  • @juliomalves The suggestion worked at making the component rerender, and my remaining bug was a separate issue regarding React needing a key prop passed into a component. I was not doing this, so React didn't know whether I changed the order of the array when rendering the html. – Ryan Millares Dec 10 '21 at 04:56
1

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
André
  • 12,497
  • 6
  • 42
  • 44