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.
Related
I have a form (Parent) which contains an input field (Child), which gets its value from a reference table (Grand-grand-child) that is displayed as a modal (Grand-child) which opens up by clicking a button attached to the input field. This is a nested structure that roughly looks like this:
I need to set the value of the input field by selecting a row in the reference table and confirming my choice with a button "SET VALUE", which means I need to pass data three levels up from Grand-grand-child to Parent through Grand-child and Child.
My state is kept in the Parent component. Is there a simple way of achieving that without using external libraries? Please offer a solution using Hooks as all of my components are functional components.
Here is the code: https://codesandbox.io/s/festive-fast-jckfl
See CreateRate component where:
CreateRate.jsx is the Parent
InputField.jsx is the Child
DataFetchModal.jsx is the Grand-child
Airports.jsx is the Grand-grand-child
Pass a change handler function from parent (where state lives) down to the grand child. The grand child should call this change handler when clicking the Set Value button.
If this is too much prop drilling
look into component composition first
if that doesn’t work out, look into context api
Update:
You mentioned your problem was trying to access the state inside Grand-grand-child from your Grand-child. In this case you can lift the state up (to Grand-child). This means lifting 'airports' up to DataFetchModal. Here is more info on lifting state.
https://reactjs.org/docs/lifting-state-up.html#lifting-state-up
Also, it appears you are running into these problems because your code is very nested and not very composable. I would suggest looking into how you could better break up your components. One way to accomplish this is using compound components.
https://kentcdodds.com/blog/compound-components-with-react-hooks
Determining how to break this up better would take some time. However, just looking at this briefly. You may be able to move your DataFetchModal to your parent. Pass a callback to the InputField to fire it off and send the identifying parameters (what input called it). Then, from the parent, compose in whatever modal body using composition. It appears you have a lookup object (objType) inside DataFetchModal. Maybe this could go away by using composition (not sure, and probably separate topic).
Update 2:
I pulled down your code sandbox and made a few changes that may help access parent level state. I moved the modal into the parent. Check it out.
https://github.com/nathanielhall/Test
There is some related threads, and a lot of opinions on this subject so I will try to summarize my findings. Notice I am a beginner so this is my best bet, and the data I gathered from related posts and this.
In general most people agree that if the parent call's a child it is bad practice. In the related post for this article there is an accepted answer, where the person answers that it is a bad practice but possible. #mat sz answer directed me on the right path. I have updated my sample for others to see. I pass a parameter to my child component. In the child component I add a listener for changes on that parameter:
useEffect(() => {
if (props.toggleClose != null) {
setToggleJobTable(false);
}
}, [props.toggleClose]);
I just toggle that parameter between true/false in my parent. Not beautiful but my best bet on how to do this in react.
Original question
I found a lot of samples in here on how to pass variables to child components, how to raise events from child components to parent components, and even how to pass a function to a child component from parent component. But what about last scenario. How to call a function in a child component from the parent. In this sample I would like to trigger the closeAll function in the child component from the parent:
https://codesandbox.io/s/toggle-all-qxkgy?fontsize=14&hidenavigation=1&theme=dark
I still dont have an answer on this, but a lot of good input in the posts. For me it sounds like the right approach here would be parsing a parameter to the child as parameter. My question is then, if I pass a parameter to the child component. How do I toogle when the parent changes that value, then my closeAll function in the child is called?
It is also stated that it could be wrong design. If you look on my very simple sample how should it else be designed? All input are welcome. I have very little experience with REACT so I am trying to understand how an experienced REACT developer would solve this simple task/sample.
It's not possible, parent components are not able to access the functions inside of child components.
You could use something like Redux or MobX to create a global state and then rely on global state for that, or you, ideally, should restructure your code in a way that does not require this, for example if your function (the one that has to be called inside of parent) changes state of a child component - move that state to the parent component, and then provide that state via props to the child component (along with a setter function, if required).
I have a component in the front-end but the code has become pretty large and wanted to try to split it so that all the rendering styles are done in a different component.
I tried using the map function but getting errors about map not being a function, maybe because the states that I want to pass on aren't arrays?
What I want is something like this:
Parent Component --> Pass all the states --> Child Component
Then, child component can just use this.state.value to display
Is there a good and easy approach to splitting up the code in cases like this where it's become too large? It's rendering 2 different looks depending on a condition and so that's where it started getting large.
The two different looks can be created as two different components, and the state of the parent components can be passed into child components as props.
In parent component you can use conditional rendering to show which ever child component you want based on the condition.
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.
I'm building an application where I would like to provide separate views for same data.
In my current implementation, data is obtained by web service call and persisted in state of App component in App.js. App component hosts (renders) another component called StackEditor, which acts as a view for this.state.components in App component.
UI elements rendered by StackEditor can be moved around, and to synchronize state of App I do it as below:
<StackEditor
components={this.state.components}
onLocationChanged={this.handleLocationChanged} />
In handleLocationChanged I update the state:
handleLocationChanged(e, data) {
this.setState(prevState => {
// event data copied to state here
return {components: prevState.components};
});
}
As state is now updated, this forces StackEditor to be rendered again, as its property components is bound to state as components={this.state.components} (see in the code snippet above).
This all works, but now I started questioning if I'm doing it right.
Q1: Should I be using state instead of props?
It seems that location of component is mutated in principle, although from StackEditor point of view, it is immutable (I can decide that change is invalid and not to update the state in event listener).
Q2: Is it possible to share part of the state between 2 components in React?
If I somehow convert StackEditor from getting components from state instead of props, will I get notification on state changed by child component (StackEditor) in my parent component (App)?
Q3: Also, are props more convenient to use than state in general?
When I created another component following HOC guidelines (https://reactjs.org/docs/higher-order-components.html) I discovered that props are easily forwarded to "wrapped" component, but not state. If I provide a function to call back via property (as I did above), "wrapped" component can easily call it, without even noticing that it's "wrapped". I don't see how I can easily notify "wrapped" component about state change in "wrapper", without writing some extra code.
If you imagine your application to be a tree of components in a well designed app it's usually like this:
the leafs are stateless components . They decide how data is rendered.
the nodes are stateful components. They decide which components and data to render.
Q1: Should I be using state instead of props?
It depends on which category of components you have (node or leaf).
Q2: Is it possible to share part of the state between 2 components in
React?
If you feel that your app has a lot of state that mutates and needs to be used by several components spread over your tree you usually start to introduce an external state management library (e.g. redux). Components can subscribe to your store and become stateless as your store now handles the state.
Q3: Also, are props more convenient to use than state in general?
They solve different problems so you can't really say that. A stateless component is usually easier to understand but has no capabilities to control anything.
Also read Identify where your state should live and When to use redux.
All that is only a rule of thumb. A lot of the time you will have components that have both state and props because they control parts of your app but delegate other parts to their children.
This all works, but now I started questioning if I'm doing it right.
As far as I can see from the code you provided this looks pretty much as it has to.