React - Parent Layout Depends on Children Content - reactjs

I have a situation where the parents class depends on if the children have content.
<div className="parent">
<div className="child1"></div>
<div className="child2"></div>
<div className="child3"></div>
</div>
For example if child1 is the only child that has content the parent class should be "a", if child1 and child2 have content the parent class should be "ab", etc. Each child maintains their own state, meaning a child could begin with content and through state changes have none at the end. I'm looking at using Higher Order Components and references to solve this issue but haven't found a great solution yet. Wondering if there's a build pattern to help with this problem.

My understanding of traditional React would suggest that if a parent component depends on the state of child components, then that state variable should really be maintained by a shared grandparent like so:
<Grandparent> //Maintains State
<Parent> // receives Grandparent state and state manipulation functions as props
<Child 1> // receives Grandparent state and state manipulation functions as props (via Parent)
<Child ...n> // same as child one.
You'll end up passing functions defined as methods on all the way down to so changes triggered on can impact the state variable on and the props are passed down new.
Passing functions and state down and up the tree can get messy, so depending on how many levels you have to your tree, and how much state you are passing around, you could take a look at redux to simplify the flow. Redux acts as a state container outside the React hierarchy, making universal state variables readily accessible at any level of the tree.

Related

React - Passing Props across the component tree

I am relatively new to React and I was wondering if you could pass components across the component tree without having to create the state variable in the parent component.
Things I understand:
You could pass props down from parent to child.
You cannot pass props up from child to parent.
I also understand that you could use context API's to avoid prop drilling. However, the Context.Provider has to be above the Context.Consumer. So that would mean I would have to create the state variables in the parent class. If I want to share the same state between two child components.
There have been times in my React application where I was forced to create a state variable in the parent to share it across two child components. Is there any way I could use the context API or some other method to create the state variable in one of the child components and share that state with another child component.

How can I call child component setState from parent component

I have 2 stateful class-based components nested within my main app, a parent class-based component. From child component 1, I've successfully called a parent callback method. From within that parent callback I want to call a method of child component 2, so I can setState of #2 without re-rendering the parent component. I've seen that many devs make the children stateless or even just omit them. However, React encourages devs to "componenatize" ... pointers plz!
if that's the case then you shoud consider lifting the state up to the parent: https://reactjs.org/docs/lifting-state-up.html
your child component should only then call parent methods to update the state, that way, you will have a unidirectional flow of data as what a react app should be. Basically, it encourages you to have a single source of truth and ensure synchronisation of data across your app. Besides it removes unnecessary logic like what you are doing right now:
What does the "single source of truth" mean?
Storing the data in the parent's state and then allowing both children to update it via setStates wouldn't violate the concept of "componentizing" as long as the two children have narrowly declared inputs. If one child needs to update data inside another child, you can jump up a context level and store it in the parent- then an update of the data from either child will trigger a render of both children ensuring the display stays synchronized with the data while keeping the data in a single place (with the parent instead of split between the children).
Bingo, yes I can use a "React ref" to call an instance method of a child component. A ref is an attribute on a component instance. So, right now my child component uses its componentDidUpdate to call a callback in my parent, and the parent callback then uses refs to call an "update" method of specific child components. These update methods setState on child component and voila.
So a colleague explained that calling setState in my main app actually will call setState on all children components (related by JSX expressions). Even though I liked the idea of nesting my event handlers within their relevant child components, it seems that the best practice pattern is to have all handlers in the main app, setState in the main app, then let React do its thing

Mutate state of children

I have two components in my react application, one is parent and the second is the child.
I pass fakedata state as a props to child and then in child component save this as state of child component. But when I change something in child it's affect on parent state and I don't want this I want it's only effect on child state.
This is how I call child component from parent :
<FakeDataAddEditComponent {...this.props} fakedata={{...this.state.fakedata}} />
and in child component this is how I set fakedata props to state :
componentDidMount() {
this.setState({fakedata:{...this.props.fakedata}},()=>{
})
}
but when I change fakedata state in child it's also changend in fakedata of parent and I don't want this.
To answer your question directly, the reason you are seeing this behaviour is because Javascript passes a reference to the original object down the props and to the state of child component. When you update the child component it is the same instance as the parent is holding.
To fix the problem you should use Object.assign to make a copy of the object, however keep in ming that you will run into problems with nested objects.
Also, if parent object mutates the state in any way after the child state changed it will pass old object as props to the child.
In general you're trying to do something you shouldn't do because you will run into trouble.
On a high level you should go for a proper state management solution like Redux of Flux.

child components communications in angularjs 1.5.x

I have an angularjs component with 2 child components. I want to call a function in product-list component when on-added output triggers in new-product component.
<h1>{{vm.store.title}}</h1>
<product-list store-id="vm.storeId"></product-list>
<new-product store-id="vm.store.id" on-added="$ctrl.productAdded()"></new-product>
The productAdded method is in product-list component and re-initiate the product list.
Any help will be appreciated.
In this case I think would be better using a common parent component and make the product-list a dumb component which receive a list and display it only. So that the parent take care of this management this list and the product-list take care of rendering the list. This, allows you to handle the state from a parent component, as new-product is dumb as well, it'll emmit changes to the parent and propagate the new list state to the child (a.k.a. product-list).
For example, consider using something similar to this raw tree of components:
<product-manager store-id="$ctrl.storeId">
<h1>{{vm.store.title}}</h1>
<product-list products="vm.store.products"></product-list>
<new-product on-added="vm.productAdded(product)"></new-product>
</product-manager>
Or perhaps:
<products-page store="$ctrl.store">
<h1>{{ $ctrl.store.title }}</h1>
<product-list products="$ctrl.store.products"></product-list>
<product-form on-save="$ctrl.productAdded(product)"></product-form>
</products-page>
The previous examples are raw representation of a component tree and its templates, in a real situation you'd have <products-page store="$ctrl.store"></products-page> because it's internal nodes would be defined by its template on the component definition.

State In ReactJS

If there are multiple components at different hierarchy levels that use the same data, should I model the data with different variables represented in the respective states of each component or should I have it as a single field included in the state of a component higher up in the hierarchy, possibly the root element? How does it affect the performance?
What I usually do, to minimize the juggling of states IF every component or thereabouts, needs something from the parent.. I will put that behavior in the parent. So, lets say I have a "Parent component" that makes an api call to get some data. If most of my children needs different splices of data off of that api call response.. I would do..
PARENT
state = from api response
----> Child Component 1 {...slice of state it needs}
----> Child Component 2 {...slice of state it needs}
---------> Sub Child Component 1 {... slice of state it needs from component 2}
Or if I can't really know for sure what data each child needs over time, I'll pass down the whole state from the parent into each of my components. If those child components have sub-components, then the child components will continue to pass the state down thru the props. You can also look into "Context" that is a nice solution if you want to leapfrop all of the passing down, and just have it available to all the children.
I usually don't worry about "performance" unless I'm dealing with literally hundreds of data sets. In which case, I tend to pass down only what the child and its sub-children needs.

Resources