Call deep child function in App.js (grand grand parent) component react - javascript

I had a case when I need to call a child function in my App.js component.
The short schema look like this :
Where I need to call the function() from the App.js, and the the function triggers something directly inside the Child 3 component.
I'm avoiding using function props drilling from the parent where this could be another problem in the future.
I tried to use Redux to dispatch the function into store, but Redux doesn't allow non-object properties to be stored.
Any help would be appreciated!

Related

How to test callback methods in react functional component when the child component elements are not completely accessible

I am using jest to test my react component. However I need to test the callback methods passed as props to children components.
My component looks something like this
function myReactComp = (props) => {
onRowEditHandler = (rowData) => {
// if this then that logic
// process and trasform data
// set some local state
// dispatch action
}
return (
<ComplexDataTableComponent data={someDataProps} onRowEdit = {onRowEditHandler} />
)
}
I need to test the onRowEditHandler as a function. I want to send arguments to this function explicitly so that specific code logic are triggered.
Now many suggestions in stackOverflow says, the best way to test closure functions in react functional components is to simulate the user behavior. For example, if there is a callback for a button, find the button on the wrapper/instance and trigger the click event.
In my case, the ComplexDataTableComponent is kind of like a container, which has many children and nested components. It is next to impossible to find a specific row element, trigger its edit button and then update the form data so that the call back is triggered.
Is there any way i can get access to onRowEditHandler apart from triggering the wrapper/instance elements?

React useState hook: passing setter to child- functional update, callback and useCallback

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.

Is the react state meant to be used within the component it is defined?

Should react component state is meant to be used in the component in which it is defined?
I faced a scenario, where a component state is updated by two different components and is passed as a prop to its child. But never used in the component where it is defined.
For example: I have a component CommonComponent which has a state, 'stateObj' and it has two child components ChildComponent and ModifyComponent.
I have one more component, CreateComponent which is a parent of CommonComponent.
I have two cases here:
During create action, CommonComponent receives props from CreateComponent and updates the state- 'stateObj' and is passed as a prop to ChildComponent
During modify action, ModifyComponent updates the state of CommonComponent using a callback and in turn the 'stateObj'
is passed as a prop to ChildComponent
Is this a valid way of using the component's state? As I understood, The state is meant to be used by its component in which it is defined. But, here I am not using the 'stateObj' in CommonComponent. but, i am just using it to send data to its child components. Am I using the state in a right way? or is there any other way of doing this?
your suggestions are really precious!
Thanks in advance.
You could move the state to CreateComponent instead of having it in CommonComponent. So, ModifyComponent and CommonComponent will have callback props which will update the state in CreateComponent.

Vue: Reasons to use props instead of referencing parent data?

In VueJS, I have seen different ways of accessing parent properties from a component. Say I want to use the parent property items in my component.
First way
The component has a props value bound to a parent property:
.js
Vue.component("example", {
template: "<div></div>",
props: ["myItems"]
});
.html
<example v-bind:my-items="items"></example>
Second Way
The child component accesses a parent's properties directly, like this:
this.$parent.items
Question
Is there a reason to use the more elaborate first method over the second? Is there an overhead to "duplicating" data like that, vs. accessing it directly when needed?
The props should be mutated in the parent component, according to the official doc :
All props form a one-way-down binding between the child property and the parent one: when the parent property updates, it will flow down to the child, but not the other way around. This prevents child components from accidentally mutating the parent’s state, which can make your app’s data flow harder to understand.
In addition, every time the parent component is updated, all props in the child component will be refreshed with the latest value. This means you should not attempt to mutate a prop inside a child component. If you do, Vue will warn you in the console
So in order to update props from child component you should use this.$emit event and send the new value in order to handle the update in the parent one.

How to access Child component state and lifecycle methods and validate in React with Jest+Enzyme?

Need help with enzyme for testing. I have checked here but it did not help: How does one access state on a nested React component wrapped by an HOC?
Here is my problem:
How can I check function called or not and state of Child component? I also need to check lifecycle, so I used mount of parent component, but haven't done that yet.
I used below when I rendered one component:
expect(searchWrapper.find('select [selected]').val()).to.equal('someId'),
but with mount, this is not working, as it complains searchWrapper.find(...).val is not a function which I believe is a cheer IO and it worked with render only. So what will be the proper way for me?
What I intend to do: On child select change, check (and/or match):
child func is called once
parent func is called once (called inside 1.)
parent state
child state
lifecyle methods like componentWillReceiveProps and componentDidMount etc
Result rendered output validation, also including some of the above.
Component is like
class ParentWrapper {
// state and other functions and lifecycle methods
render(){
....
<SearchWrapper {...props}/>
<ResultWrapper {...props}/>
}
}
class SearchWrapper {
// state
// lifecycle methods
// functions
}
and same for ResultWrapper.
Summarizing it again with some code:
I want to access state and other objects of Child node, just like we can do with root. Also access rendered objects like selected option from the select menu, for example.
// state is not a function, as it has to be called for root only, then whats the alternative
expect(parentWrapper.find(SearchWrapper).state().searchId).to.equal('someValue');
// Below also did not work, it worked when I tested SearchWrapper individually using render()
// which is a CheerIO function, but I need to use mount of parent for whole component testing
// and inter-component interactions
searchWrapper.find('.form1 select').simulate('change', {target : {value : 'someValue'}});
// sinon spy on change is triggered
expect(searchWrapper.render().find('select [selected]').val()).to.equal('someValue');
// AssertionError: expected undefined to equal 'someValue'

Categories