0

I am trying to update a single value of a 2D array.

Note that: I referred the following questions

Difference between let a=[] and new Array

Javascript multidimensional array updating specific element

Javascript : change cell value in 2D array

I am using the following code to create 2D array

export default function(
    numrows = 16,
    numcols = 10,
    initial = { value: 0, color: 'wheat' },
) {
    let arr = new Array(numrows).fill().map(function() {
        return new Array(numcols).fill(initial);
    });
    return arr;
}

And i am using the above function to generate the initial array in constructor and display it in form of table in view.

On click of a button, I want to update certain values of the array by calling the updateArray function.

The problem I am facing is that the updateArray function updates all the values of the array to "4" instead of updating only the _gridArray[1][2].value = 4; and _gridArray[0][2].value = 3;

So, My question is, How do i update only the specific values of the 2D array?

Check this CodeSandbox link for the demo of the app

class Main extends Component {
  constructor(props) {
    super(props);
    this.state = {
      gridArray: arrayBuilder() //calls above function
    };
  }

  renderTable = () => {
    return this.state.gridArray.map((data, i) => {
      return <TableRow key={i} row={data} />;
    });
  };

  updateArray = () => {
    let _gridArray = [...this.state.gridArray];
    _gridArray[0][2].value = 3;
    _gridArray[1][2].value = 4;
    this.setState({ gridArray: _gridArray });
  };

  render() {
    return (
      <Fragment>
        <div>
          <button onClick={this.updateArray}>Update Array</button>
        </div>
        <table>
          <tbody>{this.renderTable()}</tbody>
        </table>
      </Fragment>
    );
  }
}

export default Main;

I also tried separating the array generator function and tried running it outside project. It updated the array values properly. Try running the code snippet and check the values in console.

function createAndUpdate(){

//1nd method to create 2d array
  
  let arr = new Array(16).fill().map(function() {
    return new Array(10).fill(0);
  });
  console.table(arr);
  let newarr = [...arr];
  newarr[0][2] = 4;
  console.table(newarr); //value updated properly

//2nd method to create 2d array

  let arr2 = []
  for (let i = 0; i < 16; ++i) {
    let columns2 = [];
    for (let j = 0; j < 10; ++j) {
      columns2[j] = 0;
    }
    arr2[i] = columns2;
  }
  console.table(arr2);
  let newarr2 = [...arr2];
  newarr2[0][2] = 3;
  console.table("Updated table");
  console.table(newarr2); //value updated properly
  }
<h3>Open console and run this snippet</h3>

<button onClick = "createAndUpdate()">Run</button>
Gautam Naik
  • 8,990
  • 3
  • 27
  • 42

1 Answers1

2

The code for updating array is totally fine, the problem is in arrayBuilder. In your code it fills array with initial value which is just reference to the object. So array ends up being filled with the same value essentially.

I've changed array builder to clone initial object for every table cell, so the table could carry more than 1 value. The rest of the app looks fine to me.

export default function(
    numrows = 16,
    numcols = 10,
    initial = { value: 0, color: 'wheat' },
) {
    let arr = new Array(numrows).fill().map(function() {
        return new Array(numcols).fill().map(() => {return {...initial}});
    });
    return arr;
}

Please see relevant SO question: Array.prototype.fill() with object passes reference and not new instance

Andrey
  • 4,020
  • 21
  • 35