So what i'm trying to do is pass a number to the child component, which will only be passed on the first render. After that i'm trying to change the current value and pass the value from the child, back to the parent component. However i'm not able to pass price to child, as i'm receving undefined.
Not sure how I can pass the data in this context, any ideas?
function Parent(props, {price}) {
const [amount, setAmount] = React.useState("200");
function handleChange (newValue) {
setValue(newValue);
}
// We pass a callback to Child
return <Child price={amount} value={value} onChange={handleChange} />;
}
function Child (props, {price}) {
const [amount, setAmount] = React.useState("");
function handleChange(event) {
setAmount(event.target.value)
// Here, we invoke the callback with the new value
props.onChange(event.target.value);
}
useEffect(() => {
setAmount(price) //Pass value from parent if it has one
}, [])
return <input value={props.value} onChange={handleChange} />
}
For this usecase, you only need to pass one value from the parent component to its child. You are duplicating values in a way, which is unnecessary and leading to confusion. Either use the amount
or value
state variable, not both.
To fix this:
amount
state variable in both <Parent/>
and <Child/>
.setValue()
call to setAmount()
in the handleChange()
function.value
prop being passed to <Child/>
.{price}
from <Child/>
and access amount
in the useEffect()
hook instead through the value
prop.Additionally:
props
and destructured {propVariable}
syntax at the same time in the parameter list of a component. Use either not both.Parent Component:
function Parent(props) {
const [amount, setAmount] = useState("200");
function handleChange(newValue) {
setAmount(newValue);
// You can use this to test that the child component is triggering
// the handleChange() function prop passed to it.
console.log(newValue);
}
// We pass a callback to Child
return <Child value={amount} onChange={handleChange} />;
}
Child Component:
function Child(props) {
const [amount, setAmount] = useState("");
function handleChange(event) {
setAmount(event.target.value);
// Here, we invoke the callback with the new value
props.onChange(event.target.value);
}
useEffect(() => {
setAmount(props.value); //Pass value from parent if it has one
}, []);
return <input value={props.value} onChange={handleChange} />;
}
However, even all of the above within <Child/>
aren't necessary. You need just the props
in the child component, and don't need to maintain internal state in keeping with best practices i.e having a single source of truth and controlling state in parent alone, so you can modify <Child/>
further to:
function Child(props) {
function handleChange(event) {
// Here, we invoke the callback with the new value
props.onChange(event.target.value);
}
return <input value={props.value} onChange={handleChange} />;
}