While fixing a bug in some old code I came across a cumbersome implementation of an inputs list, as exemplified in the following minimal example.
When you fill both inputs, the re-order algorithm works well.
However when only one input is filled, it just copies the value into the second input.
I think it has something to do with the key property of the Array.map function - that are currently set with the indices (which is considered an anti-pattern) - however there are no IDs I can use to map the data in a more meaningful way.
I'm currently putting aside this being a bad implementation, as I want to understand what's going on with these keys (or alternatively to find out I'm mistaking and the bug is somewhere else).
class MyTest extends React.Component {
constructor(props) {
super(props)
this.state = {
isAscending: true,
placeholders: ['first', 'second'],
values: [1, 2],
customLabels: {},
}
}
reverse() {
const { values, placeholders, customLabels, isAscending } = this.state;
const sortedData = values.map((value, index) => ({
value,
placeholder: placeholders[index],
customLabel: customLabels[index],
}))
.sort((a, b) => (isAscending ? 1 : -1) * (b.value - a.value));
const newPlaceholders = [];
const newValues = [];
const newCustomLabels = {};
sortedData.forEach((dataObject, index) => {
const { value, placeholder, customLabel } = dataObject;
newPlaceholders.push(placeholder);
newValues.push(value);
if (customLabel) newCustomLabels[index] = customLabel;
});
console.log({ newCustomLabels }); // Here I can verify that `customLabels` is sorted as expected
this.setState({
isAscending: !isAscending,
placeholders: newPlaceholders,
values: newValues,
customLabels: newCustomLabels,
});
}
onChange(e, index) {
const { customLabels } = this.state;
const newCustomLabels = Object.assign({}, customLabels);
newCustomLabels[index] = e.target.value;
this.setState({
customLabels: newCustomLabels,
})
}
render() {
const { placeholders, customLabels, values } = this.state;
return (
<div>
{
placeholders.map((placeholder, index) => (
<div key={index}>
<input
placeholder={placeholder}
value={customLabels && customLabels[index]}
onChange={(e) => this.onChange.bind(this)(e, index)}
/>
{` with value: ${values[index]}`}
</div>
))
}
<button onClick={this.reverse.bind(this)}>Reverse Order</button>
</div>
)
}
}
ReactDOM.render(<MyTest />, document.querySelector("#app"));
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.6.3/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.6.3/umd/react-dom.production.min.js"></script>
<div id="app"></div>