Is there a way in ReactJS for a component to find out who it's parent is?
EDIT 1: Regardless of the merits of doing this, is there a way?
I haven't found a React way to do this - from what I can see, the idea is to pass callbacks down to the child from the parent, and the child calls the callback - unaware of the fact that the callback is actually on the parent.
I've tried setting an "owner" property, and that idea seems to work, but I wonder what's the best approach?
e.g.
<Parent>
<Child owner={this}/>
</Parent>
Then in the child component, I can do owner.method, and it seems to work fine. I know this isn't a true parent/child relationship, but is the closest I've found in my tests.
Some may say that callbacks are a cleaner way of doing this, but the parent/child relationship for some things (e.g. RadioButtonGroup and RadioButton) seems natural and would benefit from knowing this relationship, in my opinion.
EDIT 2: So it's not possible?
The thing that I don't like about the idea that it's not supported is
that HTML can be marked up with zero javascript - and it has implied,
default functionality - some elements are required to have parents -
they are defined as children of other elements (e.g. ul and li). This
can't happen in JSX because if there is interaction between the
elements - there has to be javascript events that bind the
components together - every single time you use them. Designers can't
simply write HTML like syntax - Someone has to step in and put some
javascript bindings in there - which then makes the maintenance
harder. I think the idea makes sense for overriding default behavior,
but default behaviors should be supported. And defaults would
require knowing either your parent, or who your owner is.
There are a number of benefits to not doing this, the main two are: reusability and encapsulation.
TL;DR you probably don't want to do this ever.
Let's say our RadioButton has this public interface:
<RadioButton active={true} onSelect={function(event){}}>text</RadioButton>
We could construct another component called SuperRadioButton, which might have a different way of presenting itself, but still have the same public api as RadioButton, so it's a valid child of RadioButtonGroup.
If we're accessing the parent, then the parent's internals become part of the public api of these components, and we need to be much more careful with how we change our code, because a change in any of these components could cause the entire application to break.
Callbacks. Owner properties. Passing events out to be caught by the root in the tree. Passing the root down through contexts.
There are ways, yes, but they're contrary to the conceptual model of react, which is to be explicitly top down at all times. The short version is "you can, but don't."
The fundamental problem is that you don't want a child mutating outside its parent's knowledge.
That means that the sole exception to this is the root of the component tree, so it's semi-legit to pass a member of that control downwards in props or contexts then to "pass things up" by telling the root, which may then repaint itself.
The application layer Flux does something not terribly dissimilar to this, but passes things outside of the component heirarchy entirely to a dataStore, which broadcasts things back in with events.
Related
Specifically used just to view the heights/widths (getBoundingClientRect) of elements. I recently encountered a need to find all the separate heights of a dynamic amount of child elements to perform a calculation. I added a ref within the child component, and passed a function down from the parent in an attempt to update the parent's list of child dimensions (which was in state). I found this to be overtly complex and confusing and unreliable. So, in the parent, I just did a simple for loop with getElementById after giving each child an id of child-${index}.
I know you are NOT supposed to do any direct DOM manipulation in React; however, if your goal is read some data only, then is it an issue or bad practice?
It might not be a problem right now, but I would consider using getElementById instead of a ref bad practice in general (or at least call it "a workaround").
1
getElementById works "outside" of React, so you are not using React here.
That might work for now, but also might interfere with what might do React at some time.
E.g. you might access or hold a reference to a DOM node, and React might decide to remove that node while you were reading it. I don't see why this might happen in your
example, but when using two separate systems it is hard to keep track of the possible consequences.
2
With the id child-${index} you have introduced a logical dependency (coupling) between the parent and the child.
The id child-${index} acts as a reference here, and has to be kept in sync manually.
This might be easier in a short term, but is actually more complex as a general approach (e.g. less maintainable, reusable, ...).
You could say, Reacts whole purpose is to avoid such complexities.
Your components should be as independent of each other as possible, and should only communicate through the props.
suggestion
I suggest to avoid both getElementById and passing a ref, and have the children know their size (e.g. using a custom hook),
and pass only the sizes up to the parent (not the ref).
If that is not possible, I would prefer to use refs.
Also note that "confusion" is not the same as "complexity": Confusion can be decreased by acquiring more information, but complexity is an
inherent property of a system.
I am wondering what is the recommended way to communicate between ReactJS components. I took a look at a related question. However, I did not find the answer sufficient. The key approaches seem to be the following:
Assume that only childs / parents communicate.
Communication from parent to child is realized by setting props, the reverse is realized by passing a callback as a prop.
This has the following disadvantages:
Since siblings can't communicate directly, all state which has to be passed back and forth between siblings has to be stored in their common parent. This means that the parent has a lot of state which it doesn't really need.
Passing callback is rather inelegant.
What I would like to do is to add to components methods / members in order to establish communication. I am thinking along the lines of RxJS. This would mean the following:
I accept that communication is out of the scope of functionality handled by ReactJS. This seems to be the case anyhow.
The members of classes need to be persistent. For example, a parent component should not create a new <Child /> during each call to its render function since in this case all the subscriptions would have to be reestablished. Instead the constructor would have to create a this.child = <Child /> object and in the render call render {this.child} instead.
My question is: Is component communication somehow handled by ReactJS or is this something that should be taken care of by the developer in some other way?
In the first case: Is there a scalable and elegant way that communication between components can be realized in ReactJS? Is the rationale of the developers of ReactJS is done in the way described above or is there something I am missing?
In the second case: How should the components communicate instead?
Well there are two established way in React to communicate between components.
Observable architechture: Mobx
Flux like architechture: Redux
Note: Look at mobx if you are not sure what to start with :)
What is the best way to test React's Components in Unit Tests?
The first problem is decorators (or HOCs). We don't want to test them, but without them it is really hard to mount deeply to test how it works as a components; but in order to make them work we have to mock all chain of Providers (which is ~3 components in our case, plus contexts, etc), and again, it is too fragile from my point of view.
Next question is about the logic inside components. I know, there are tons of articles with cool advice like "don't use logic inside your components", but we often need to maintain local state (like banners, etc). Should it be tested just with shallowMount, or it doesn't cost it too? Also lifecycle methods, if we start to check it, doesn't it make our tests too brittle and too much know about implementation?
And the last question is about the markup. Should we check anything inside the React Component? I read all sorts of tutorials, and I think that finding by tag is the worst example ever (I don't even want to go into details here). Jest snapshot feature for me doesn't seem a good choice too (I see absolutely the same problems here too). What I see could be helpful – just checking that different components are rendered when difference props are passed (like Loader and Offer, for instance, respectively), but sometimes they are children of some container itself, and shallowRendering doesn't work, which takes us back to the initial point.
To conclude, I see the point only in two things:
Testing logic for internal state (invoking methods and looking into new state)
Looking at rendering of components which render depending on props.
Second point can be really hard (because of deep nested children), so for now I am leaning towards rendering just a component (check that it didn't fail – in a shallow way), and checking logic by invoking methods and checking state after.
What are your strategies?
I've been doing development mostly in AngularJS, recently I was looking into Vue.js and reading its guide, on one page it mentions:
By default, 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 default is meant to prevent child components from accidentally mutating the parent’s state, which can make your app’s data flow harder to reason about.
This is from https://vuejs.org/guide/components.html#Prop-Binding-Types.
I'm wondering if there are any principles of when to use two way binding, and when not to?
For the case where the child component needs to manage an array variable, it seems that two way binding would make sense.
For example, say I want to make my own Vue.js or AngularJS version of http://selectize.github.io/selectize.js/.
If two way binding is used, I would just pass the parent component's array to my Vue.js or AngularJS selectize component, and let the selectize component manage it.
If two way binding is not used, it seems the alternatives would be:
a. Either the parent component would either have to manually update the array when an item is added/deleted
b. Or the parent would have a function that manually sets the array, this function is then passed to the child component
c. The child component dispatches an event which the parent component listens to, and updates its array
I think these are the alternatives? Both seem more verbose and does not appear to provide much benefit.
This is one example, but I think many components would have this issue, another example would be if I have a product-selector component, it would be convenient to just pass in an array variable into this component, and let the component manage the array to reflect the selected products.
My main questions on this are:
Is my idea of the alternatives to two way binding correct?
For the mentioned cases, is there an advantage to using one-way-down binding? (I do not see the alternatives providing much advantage to avoid "accidentally mutating the parent’s state")
If (1) and (2) are correct, what is an example where one-way-down binding, provides a clear advantage to avoid "accidentally mutating the parent’s state"?
"one-way-down binding" is just a principle, similar to OO's Encapsulation, to reduce code complexity.
In my opinion the author didn't mean not to use "two way binding" (actually vuejs support that), just mention you don't abuse it.
In your examples, the product-selector is similar to native input, surely I think you can use two way binding, just like v-model does.
I was wondering something about the reverse data flow in a React app.
Considering this question: data flow in react application and this article http://facebook.github.io/react/docs/thinking-in-react.html
We can see that the "normal" way to communicate from child to parent component is using callback passing through this.props.myCallback. (the StackOverflow article is a good example)
My questions are:
I understand the concept but what if we have deeper components? We would have to pass this callback to every component between the top parent component who hold the state and the actual triggering component. And if there is 3 to 4 components between them, I would have to pass the callback using this.props in each component.
Why not using an Event Emitter? I could send an event from the deep child component and then listen to this event in my top state parent component. This way we could avoid all the code between these two.
Please tell me what are your thoughts about this!
I learnt the hard way that it is a good practice to keep as much logic as possible in the highest level in the hierarchy of your components. Dan Abramov well expressed this idea in the article Smart and Dumb Components, where Smart Components are those that hold the logic, whereas Dumb Components are just meant to display.
So yes, the callback mechanism works well when you simply want to update the father's state, or you want the father to do an action whose logic you do not want to belong to the child.
When you have anything slightly more complicated than this I would suggest you go with a Flux-ish architecture of your taste. Flux indeed uses node's EventEmitter to communicate with the components.