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 -
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>
);
}