I bet has been answered a million times, but I haven’t had luck searching in google. I don’t know a concise way to phrase the question.
As learning project, I am trying create a simple html editing tool, that includes a side panel where you can edit different properties of each layout element, like in figma. The problem is that in said panel, the input values do not update when I select a different element.
The values in the target objects are changed well, according to plan, but the problem is that the input values persist when I change from one object to another.
I created a demonstration isolating the problem here https://codesandbox.io/p/sandbox/react-question-example-3qlyp5 (also below). Here I can select among the two objects, and correctly alter the ‘x’ field of said object by editing the input. However, when I select the other object, the input value is not updated to show the value of the new object’s field. Only the first selection updates the field value correctly.
I am tempted to remove the input and immediately show it again, as to re-instance it, but that’s sub-optimal. Since it’s a learning project I better ask.
import "./styles.css";
import { useState } from "react";
const exampleThings = [
{
x: "12px",
i: 0,
a: "foo",
},
{
x: "5px",
i: 1,
a: "bar",
},
];
const positionParse = (pos) => {
const parsed = parseFloat(pos);
if (isNaN(parsed)) throw new Error("oops");
return parsed;
};
function PositionEditor({ setPositionDef, positionDef }) {
const [hasError, setHasError] = useState(false);
const [value, setValue] = useState(positionDef);
const changed = (e) => {
setValue(e.target.value);
try {
positionDef = positionParse(e.target.value);
setHasError(false);
setPositionDef(e.target.value);
} catch (e) {
setHasError(true);
}
};
return (
<input
type="text"
value={value}
onChange={changed}
style={{ borderColor: hasError ? "red" : "unset" }}
/>
);
}
function ThingSelector({ select, t }) {
return <button onClick={select}>Select thing {t} </button>;
}
export default function App() {
const [things, setThings] = useState([...exampleThings]);
const [selectedThing, setSelectedThing] = useState(undefined);
const selectThing = (i) => {
const thingIndex = things.findIndex((thing) => thing.i === i);
console.log("select thing", thingIndex);
setSelectedThing(things[thingIndex]);
};
const editThingPositionDef = (position) => {
const selectedThingId = things.findIndex((t) => t.i === selectedThing.i);
const newThings = [...things];
const newSelectedThing = {
...selectedThing,
x: position,
};
newThings[selectedThingId] = {
position,
...newSelectedThing,
};
setThings(newThings);
setSelectedThing(newSelectedThing);
};
return (
<div className="App">
{things.map((thing) => {
return (
<ThingSelector
select={(e) => selectThing(thing.i)}
t={thing.a}
key={thing.i}
/>
);
})}
{selectedThing === undefined ? (
<p>Select something</p>
) : (
<>
<p>
Editing: {selectedThing.a}. My x is {positionParse(selectedThing.x)}
</p>
<PositionEditor
setPositionDef={editThingPositionDef}
positionDef={selectedThing.x}
/>
</>
)}
</div>
);
}