27

I'm looking to modify and array in react and insert elements on specific index. This is how my state looks like:

this.state = {arr: ['', '', '', '' ]}

What I wanna do is to compile this arr[index] = 'random element' to react js setState syntax. What I tried to do was:

this.setState({ arr[index]: 'random element' })

but failed, ty!

isherwood
  • 58,414
  • 16
  • 114
  • 157
alex1997
  • 431
  • 1
  • 5
  • 13

6 Answers6

109

enter image description here

Clone the current state using slice(). By doing this, the original state remains unaffected till setState(). After cloning, do your operations over the cloned array and set it in the state. The previous answer will mutate the state. Read about this here

let a = this.state.arr.slice(); //creates the clone of the state
a[index] = "random element";
this.setState({arr: a});
Pranesh Ravi
  • 18,642
  • 9
  • 46
  • 70
  • 7
    Another way of creating a deep copy of an object, including arrays is to use the spread operator, as follows: `let myElmClone = {...this.state.myElm};` – RoyB Oct 16 '18 at 14:42
  • Just here to say, despite having faced an issue in Vue JS, I stumbled upon state update related gotchas in Stencil. And this comment helped me. Thanks! – Rutwick Gangurde Nov 06 '20 at 10:01
11

use spread operator https://codeburst.io/javascript-es6-the-spread-syntax-f5c35525f754

let newChild = "newChild"

this.setState({
    children: [
        ...this.state.children,
        newChild
    ]
})
Aldo Makmur
  • 111
  • 1
  • 3
6

UPDATE

Just use Object.assign() as suggested here to make a copy of your state.

Thus, you can do it as follows :

let new_state = Object.assign({}, this.state); 
let a = new_state.arr;
a[index] = "random element";
this.setState({arr: a});

Hope it helps.

Boky
  • 11,554
  • 28
  • 93
  • 163
  • 1
    Wow, I should have gone deeper, that looks so easy and nice. Meanwhile I found a method as well, but this one is definitely the best way to do it, ty! – alex1997 Oct 09 '16 at 09:11
  • 8
    This is the bad way of implementing You should not mutate the state directly! – Pranesh Ravi Oct 09 '16 at 11:55
  • 2
    Agreed, `let a = this.state.arr;` is merely making another reference to the same array, which you can't mutate directly. – Steve Taylor Jul 06 '17 at 03:25
  • a is reference of the state arr. Which will cause strange behavior because you are changing its state on line 3. You should create a copy of the array on line 1 (not a reference of it) – eveevans Apr 03 '18 at 18:12
5

Something like this will work.

State Array

const [myArray, setMyArray] = useState<string[]>([])

Add to state array

function onChangeArray(newValue: string) {
    setMyArray(myArray => [...myArray, newValue)
}
Ruchira Nawarathna
  • 1,137
  • 17
  • 30
1

Two Ways to do:

  1. Using concat :

NOTE: It is not allowed to use the array push method, because it mutates the array. It doesn’t leave the array intact but changes it. Instead, there should be a new array created which is used to update the state.

Array concat method creates a new array, leaving the old array intact, but also returning a new array from it.

this.state = {
      value: '',
      list: ['a', 'b', 'c'],
    };

this.setState(state => {
const list = state.list.concat(state.value);
return {
        list,
        value: '',
      };
});
  1. Using ...spread operator :
this.state = {
      value: '',
      list: ['a', 'b', 'c'],
    };

this.setState(state => {
const list = [...state.list, state.value]; <--insert in end -->``
const list = [state.value, ...state.list]; <--Or insert in start -->
return {
        list,
        value: '',
      };
});

Reference : https://www.robinwieruch.de/react-state-array-add-update-remove/

vik_78
  • 1,107
  • 2
  • 13
  • 20
1

Immer is a common dependency to help with this kind of thing. In this example, you would do something like

import {useImmer} from "use-immer"

export default function MyComponent(props) {
   const [state, setState] = useImmer({arr: ['', '', '', '' ]})

   // .... some time later

   setState(draft => {
       draft.arr[index] = newValue
   })
}

And Immer will take care of making sure that your state is updated immutably and correctly.

kybernetikos
  • 8,281
  • 1
  • 46
  • 54