Home > Back-end >  Javascript / React - How to update the values of a multidimensional array with the values of a `sele
Javascript / React - How to update the values of a multidimensional array with the values of a `sele

Time:07-19

I'm trying to update the values of a multidimensional array with the values of a select input inside of a forEach loop. It's one array that holds two inner arrays. Every time I change the values with the select input, both inner arrays get updated. How can I get the inner arrays to update individually? codesandbox - enter image description here

CodePudding user response:

Update the state fxChoices considering it as a multi-dimentional array. Please refer the code-sandbox here.

Try to set the state as the value of each drop-down. Don't use the drop-down only to change the state, but use it to view the actual state that you've set.

CodePudding user response:

Organize your component like below. Now it's just a matter of changing NUMER_OF_INPUTS as many inputs you want.

const NUMER_OF_INPUTS = 2;

function App() {
  const [fxChoices, setFxChoices] = React.useState(
    Array.from({ length: NUMER_OF_INPUTS }).map(() => [[]])
  );

  console.log("fxChoices", fxChoices);

  const onChangeHandler = (compIndex, optionIndex, option) => {
    setFxChoices((prevState) =>
      prevState.map((item, itemIndex) => {
        if (itemIndex === compIndex) {
          const copyItem = [...item];
          copyItem[optionIndex] = option;
          return copyItem;
        }
        return item;
      })
    );
  };

  return (
    <div className="App">
      {Array.from({ length: NUMER_OF_INPUTS }).map((_, j) => {
        return (
          <div key={j}>
            <p>bus{j   1}</p>
            <SelectComponent compIndex={j} onChangeHandler={onChangeHandler} />
          </div>
        );
      })}
    </div>
  );
}

const SelectComponent = ({ onChangeHandler, compIndex }) => {
  return Array.from({ length: 2 }).map((_, i) => (
    <div key={i} style={{ display: "flex", flexDirection: "column" }}>
      <select
        onChange={(e) => {
          onChangeHandler(compIndex, i, e.target.value);
        }}
        className="effect-select"
      >
        <option value={`bs${i   1}-fx${i   1}`}>{`FX${i   1}`}</option>
        <option value="reverb">Reverb</option>
        <option value="delay">Delay</option>
        <option value="chorus">Chorus</option>
        <option value="chebyshev">Chebyshev</option>
        <option value="pitch-shift">PitchShift</option>
        <option value="compressor">Compressor</option>
      </select>
    </div>
  ));
};

ReactDOM.render(<App />, document.querySelector('.react'));
<script crossorigin src="https://unpkg.com/react@16/umd/react.development.js"></script>
<script crossorigin src="https://unpkg.com/react-dom@16/umd/react-dom.development.js"></script>
<div class='react'></div>

NOTE: Try to think like building boxes when designing components.

CodePudding user response:

Maybe it is easier to map you multidimensionnal array to access the indexes easily like below

   import { useState } from "react";
import "./styles.css";

export default function App() {
  const Options = () => {
    const [fxChoices, setFxChoices] = useState([...Array(2)].map(() => [...Array(2)].map(() => null)));
    console.log(fxChoices)
    return (<>
      {fxChoices.map((item, i) => (
      <div key={i}>
        <p>bus{i   1}</p>
      <div style={{ display: "flex", flexDirection: "column" }}>
        {item.map((_, index) => <select
          onChange={(e) => {
            fxChoices[i][index] = e.target.value
            setFxChoices(fxChoices);
            console.log("fxChoices", fxChoices);
          }}
          className="effect-select"
        >
          <option value={`bs${i   1}-fx${i   1}`}>{`FX${i   1}`}</option>
          <option value="reverb">Reverb</option>
          <option value="delay">Delay</option>
          <option value="chorus">Chorus</option>
          <option value="chebyshev">Chebyshev</option>
          <option value="pitch-shift">PitchShift</option>
          <option value="compressor">Compressor</option>
        </select>)}
      </div>
      </div>
      ))
      }
      </>
      );
  };
  return (
    <div className="App">
      <Options />
    </div>
  );
}
  • Related