I have a group of TextFields within a material-ui dialog. The textFields are populated by JSON, and example of which can be seen below. As it is now, I can populate TextFields, but I cannot update them. I cannot enter any more text into these TextFields after they have been populated.
This is how my TextFields look
const [singleSizing, setSingleSizing] = useState("");
const SizingTextFields = ({ val, label, disabled, select }) => {
return (
<TextField
value={val}
label={label}
variant="outlined"
onChange={(e) => updateSingleSizing(e.target.value)}
style={{ margin: "1em", minHeight: "1em", minWidth: "15em" }}
select={select}
disabled={disabled}
/>
);
};
function updateSingleSizing(newData) {
for (var i = 0; i < singleSizing.length; i++) {
if (singleSizing[i].Domain !== newData) return singleSizing[i].Domain === newData;
if (singleSizing[i].Experience !== newData) return singleSizing[i].Experience === newData;
if (singleSizing[i].SizingContact !== newData) return singleSizing[i].SizingContact === newData;
if (singleSizing[i].SizingComments !== newData) return singleSizing[i].SizingComments === newData;
}
}
My JSON example:
{
"Domain": "Stack Overflow",
"Experience": "SO",
"SizingContact": "Ciaran Crowley",
"SizingComments": "Test update 2"
}
The singleSizing object is not updated when the text changes from the TextField's onChange event. The updateSingleSizing function just returns the new values but it doesn't update the singleSizing object.
So we need a function to update the singleSizing object. The onTextChange function updates the singleSizing object (more about spread syntax) when the TextField text changes.
const onTextChange = (e) => {
const id = e.target.id;
const value = e.target.value;
setSingleSizing({
...singleSizing,
[id]: value
});
};
And the TextFields updated with id property to update the actual property of singleSizing object.
<SizingTextFields
id="taxonomyId"
val={singleSizing.taxonomyId}
label={"Taxonomy Id"}
/>
<SizingTextFields
id="domain"
val={singleSizing.domain}
label={"Domain"}
/>
<SizingTextFields
id="experience"
val={singleSizing.experience}
label={"Experience"}
/>
....
Also, the TextField's select property expects child component and options. So the SizingTextFields function updated with child component.
const SizingTextFields = ({
id,
val,
label,
disabled,
select = false,
options = []
}) => {
return select ? (
<TextField
id={id}
value={val}
label={label}
variant="outlined"
onChange={onTextChange}
style={{ margin: "1em", minHeight: "1em", minWidth: "15em" }}
select
SelectProps={{
native: true
}}
disabled={disabled}
>
{options.map((option) => (
<option key={option.value} value={option.value}>
{option.label}
</option>
))}
</TextField>
) : (
<TextField
id={id}
value={val}
label={label}
variant="outlined"
onChange={onTextChange}
style={{ margin: "1em", minHeight: "1em", minWidth: "15em" }}
disabled={disabled}
/>
);
};
The updated codesandbox
You should use setSingleSizing function to update your state. You should not mutate your state directly as in your updateSingleSizing function. Also you are returning a boolean by using the === operator. Try something like this (I am not impelmenting your array logic.)
onChange={(e) => setSingleSizing(e.target.value)}