I've been wrapping my head around this for a while and I'm sure it's something simple but I cant quite get it to click. Learning React I am trying to pass a state as an argument from a child to a parent
The Child:
handleSubmit() {
this.setState({finalValue: this.state.inputValue})
this.props.changeFont(this.state.finalValue)
}
The Parent:
<Fonts
changeFont={()=> this.setState({fontState: this.state.finalValue})}
/>
Obviously this code doesn't work currently but that's essentially what I'm trying to do; pass the this.state.finalValue value as an argument to be used in the parent so I can use it in the parent component as a value.
setState is asynchronous and does not immediately mutate this.state, so if you want to perform an action immediately after setting the state on a state variable you should use setState callback.
setState(updater, [callback])
Child:
handleSubmit() {
this.setState({finalValue: this.state.inputValue},
()=>this.props.changeFont(this.state.finalValue)) //callback
}
Parent:
Pass parameter to function from the child component
<Fonts
changeFont={(finalValue)=> this.setState({fontState: finalValue})}
/>
Related
I'm currently accessing the state of a parent component in a child component through the use of callbacks, but I'm not quite sure how it works:
export default function parentComponent({ type }) {
const
[inEditMode, setInEditMode] = useState(false)
return (
<>
<div className={containerCssClasses}>
<childComponent onCancel={() => { setInEditMode(false); }} type={type} />
here, the parent component is calling the child component and passing an anonymous function to the component for it to call back.
In the child component:
function childComponent({onCancel}) {
return (
<div>
<Button onClick={() => onCancel()} variant="link" >
</div?
);
}
I am a bit confused how this is able to work properly if the child component doesn't have access to setInEditMode(). I understand that when passing a function to another function (in this case, a component), it is passed by reference. But does that necessarily mean all of the variables within that function are passed by reference as well? I am new to react (and javascript), but when I looked this concept up I couldn't find a good explanation.
Your implementation is the right way to go. More than callbacks these functions you pass down to child components are call props and I invite you to read the documentation about them.
https://reactjs.org/docs/components-and-props.html
You can also find very detailed articles about it:
https://itnext.io/what-is-props-and-how-to-use-it-in-react-da307f500da0
Whatever you'll pass from the parent to the child can be used in the child component as if it was called in the parent one.
In your case the child is indeed gonna trigger setInEditMode(false)
As you're not passing any variable to it you can actually call it as such:
<Button onClick={onCancel} variant="link" >
The parent component's state you pass to child component as props is not updated as parent's state is changed. so, you need a callback function to access parent's current state at any given time. Also, if you have dependent state value in parent and child component or rather multiple components, you can move it to reducer if you're using redux for state management.
I have a few questions related to each other regarding React hooks: useState and useCallback.
When exactly is a functional update required?
1.1. If the setter function receives a function its argument will ALWAYS be the previous state?
If I want to update the parent state from the child component, how should I pass the setter to the child- wrap it in another function as a callback as explained here? just pass it directly as suggested here?
2.1. What are the reasons and advantages/disadvantages of each approach?
If I can just pass it directly and I am using memo, is useCallback required as explained here?
If I want to use the most recent state data when updating the parent state from the child, how should I do this?
4.1. Is passing a callback to the child useful in that case?
1. When exactly is a functional update required?
You may need to update any state on your component. For example, you are getting user from server via api and you need to store that user on your component. To do so, you need useState to store that user object. Here is the example:
const [user, setUser] = useState({}); // declaration
let newUser = u; // u is coming from api
setUser(newUser);
1.1. If the setter function receives a function its argument will ALWAYS be the previous state?
Yes. setter function like setState is used in class component. Here is the example of only update a state field:
this.setState({username: 'khabir'});
here you are updating state using previous state:
this.setState(prevState =>{
return{
counter : prevState.counter +1
}
})
2. If I want to update the parent state from the child component, how should I pass the setter to the child- wrap it in another function as a callback as explained here? just pass it directly as suggested here?
Both examples are same. you can use anyone.
3. If I can just pass it directly and I am using memo, is useCallback required as explained here?
If you pass any function reference to the child component from parent component, it is being created on every render of Parent and hence prevProps and props is not the same anymore even though they are.
To apply the memo, we need to make sure that function reference is not unnecessarily recreated on every render of Parent. That's why useCallback is used. Please read that article completely for better understanding.
4. If I want to use the most recent state data when updating the parent state from the child, how should I do this?
You can not update parent state directly from child component but you can send function reference to child component and call that function from child component that defined (the function) on parent component. In that function body (in parent), you can update your state of parent component.
4.1. Is passing a callback to the child useful in that case?
Yes as I said on the answer of question number 4.
My question is about life cycle methods in react, now i have this scenario:
Some data are fetched by ajax in componentDidMount in the parent component and then this data passed as a prop to as the child component, now we are in the child so we can implement different life cycle methods,
componentDidMount: can not see the true value of the prop for example logging date in it returns empty array instead of the desired array
componentWillMount: the same.
componentWillReceiveProps: the same if not use nextProps
componentDidUpdate: logging data returns the desired data passed as prop
render: returns the desired data
So should i always be forced to call my data in componentDidUpdate or render???, Is there a way to manage that without redux??
Your child's componentWillMount and componentDidMount may only be receiving an empty array (I assume this is a default) because the Child component is instantiated before the API result is returned e.g. <Child result={result} /> as opposed to result.length > 0 && <Child result={result} />. Mount only happens once and then componentDidUpdate happens after for every prop change.
Assuming that you are just displaying the data passed down, it is perfectly acceptable to handle it in render. Otherwise if you want to perform additional side-effects then check for it's completeness in the parent component (above paragraph) at which point you should be able to see the full value in the child's componentDidMount. Alternatively you can perform the completeness check in the child's componentDidUpdate as you suggest and handle it there instead.
In my react js app, I can't seem to use the state value as props for the child component.
In the parent component, constructor, the app has a null state called selectedWarehouseID.
This state(selectedWarehouseID) should update with some information in the componentWillMount() method.
Now, in the render method of the parent component I am embedding another child component that has this state as a props.
<ItemChooser
productsByWarehouse = { this.state.selectedWarehouseID }
/>
Now here's the problem, in the child component, the value of this.props.productsByWarehouse is always null. I found a nice explanation of why this happens, but how to wait for the data that updates in the parents componentWillMount() to access the updated value of the state that being passed in the child component props?
Possible solutions are:
1. You are storing the props value in state of child component so, Update the state of child component whenever any change happen to props values (state of parent). For that use componentWillReceiveProps lifecycle method.
componentWillReceiveProps():
is invoked before a mounted component receives new props. If you need
to update the state in response to prop changes (for example, to reset
it), you may compare this.props and nextProps and perform state
transitions using this.setState() in this method.
Like this:
componentWillReceiveProps(newProps){
this.setState({
value: newProps.productsByWarehouse
});
}
Note: Replace value by the actual key in which you are storing the value.
2. Don't store the props values in state of child component, directly use this.props.productsByWarehouse, Whenever you change the parent state values, child will automatically get the updated value in props.
I found out that my argument passed from parent to child component through refs is either undefined or an actual event instead of what I passed in.
What is the right way to actually pass argument from parent to child component's function? I am using refs but seems its not really passing anything in term of function argument.
I show the case here:
https://codepen.io/adamchenwei/pen/gLMaPo/?editors=0010
Basically if you see the line where I wrote console.log('child argument should be string'); it should be an argument actually passed instead of an event.
I wonder if I did things wrong.
For this scenario, I NEED to evaluate event in parent component and decide how I want to run the child function, with specific arguments passed in accordingly.
There are only two way to access parent props in child component. you can achieve this in following two ways:-
Pass values into child component from parent via props
Set values in state and dispatch action from child to fetch values from state.
Instead of using ref, I would use state and props:
parentDoThing(event) {
const lifeTerms = {
heaven: 'yeeeeey',
hell: 'nooooooo',
}
if(event) {
this.setState({ lifeTerms: heaven });
} else {
this.setState({ lifeTerms: hell});
}
}
render() {
return (
<section className="parent-comp"
onClick={this.parentDoThings}>
<ChildComponent
lifeTerms={this.state.lifeTerms}/>
<h1> Whats in App {this.state.text}</h1>
</section>
);}
And on child component:
render() {
return (
<section className="child">
<section>this life is {this.state.life} </section>
<button onClick={this.doChildThings.bind(this, this.props.lifeTerms)}> Button </button>
</section>
);
Resolved my issue by using componentWillUpdate in combine with using parent level state passed into child as props to trigger event inside the child, because I do not want any trigger inside the child to trigger the change provided by the parent.