Reputation: 91
I get output from an api and store it in a state setInfoMetrics(data.info);
And I put this value in the input value
| the value is displayed correctly but I cannot change the value
const [infoMetrics, setInfoMetrics] = useState([]);
useEffect(() => {
const fetchMetricsInfo = async () => {
try {
const { data } = await axios.get(
`API ADDRESS`,
{ headers: { Authorization: `Bearer ${token}` } }
);
setInfoMetrics(data.info);
} catch (error) {
console.error(error.message);
}
};
fetchMetricsInfo();
}, []);
THIS IS MY INPUT AND I CAN'T CHANGE THIS VALUE:
<div className="form-row">
<div className="col-md-12 mb-3">
<div className="titrExplain">Title</div>
<input
value={infoMetrics.summary_interpretation}
type="text"
className="form-control"
name="summary"
placeholder="Summary"
required
onChange={(e) => setSummary(e.target.value)}
/>
</div>
Upvotes: 1
Views: 2063
Reputation: 67
I have seen a lot of answers that involve implementing onChange events to make the input editable. Its so difficult to understand why so many offer bad advice when it comes to setting the value of a React input. It would be better to read the manual on all the input control properties, particularly the part about 'defaultValue'. All of this business with implementing onChange events because when you set the value of the text input you can't edit it is so very easy to overcome and you don't need hooks for that. Using the onChange event bandaid, simply generates tons of events that simply are not needed.
Consider the following Custom control:
export default function TextInput({name, initialValue}:
{name:string, initialValue?:string}) {
return(<input type="text" name={name} defaultValue={initialValue}/>)
}
Right off the bat, when this control renders the initial value becomes the control value and then the control can be edited like any other web form input.
If you want the control to respond to hooks then in the parent form you can use State as follows:
export default function ParentForm() {
const values = ["value 1", "value 2", "value 3"];
const [index, setIndex] = useState(0);
const [someValue, setSomeValue] = useState(values[index]);
const modTheValue = (event: any) =>{
if(index < 2)
setIndex(index+1);
else
setIndex(0);
}
useEffect(() => {
setSomeValue(values[index])
},[index])
return(
<form>
<TextInput name="someInput" initialValue={someValue}/>
<button type="button" onclick={modTheValue}>Change It</button>
</form>
)
}
Here when you click Change it, the index state variable gets updated. Then sometime later useEffect detects a change in index, and then calls setSomeValue with a new value, this causes the TextInput to re-render and gets the current someValue as the initial value.
Upvotes: 1
Reputation: 86
//this is my sate :
const [infoMetrics, setInfoMetrics] = useState([]);
useEffect(() => {
const fetchMetricsInfo = async () => {
try {
const { data } = await axios.get(
`API ADDRESS`,
{ headers: { Authorization: `Bearer ${token}` } }
);
setInfoMetrics(data.info);
//case 1
//your summary functions
setSummary(/*what you want*/)
} catch (error) {
console.error(error.message);
}
};
fetchMetricsInfo();
}, []);
//Case2
//listening on infoMetrics changes and do something
useEffect(()=>{
//your summary functions
setSummary(/*what you want*/)
},[infoMetrics])
//THIS IS MY INPUT AND I CAN'T CHANGE THIS VALUE:
<div className="form-row">
<div className="col-md-12 mb-3">
<div className="titrExplain">Title</div>
<input
value={summary}
type="text"
className="form-control"
name="summary"
placeholder="Summary"
required
onChange={(e) => setSummary(e.target.value)}
/>
</div>
Value and onChange, attributes of should be the same set [value,setValue] of useState. Case1 and Case2 choose one and it might work.
Upvotes: 1