I want to pass my props right to my children's component.
I don't want to pass them to children and then to a decomposition component. I want to make it easier and faster.
I wondered, is it okay if I pass my props this way? Everything works as intended.
Or do I break some unknown for me rules? If I break them what can happen otherwise? If I don't break them and it's the bad approach anyway, please, explain to me why?
export function ParentComponent() {
const [myProp, setMyProp] = useState(false);
return (
<div>
<ChildrenComponent>
// Nested component gets props right here
<DecompositionComponent myProp={myProp} setMyProp={setMyProp} />
</ChildrenComponent>
</div>
);
Link to a code
P.S. I know about "render props" and useContext.
This is a perfectly valid way of sending props to components with component composition. It's also a powerful pattern to use as it can make your components more reusable, and you avoid deep prop drilling.
Related
I have a React component with many props (13 props and 9 event handle props) to pass to this component:
<MyComponent
prop1={prop1}
...etc...
prop13={props13}
onEventProps1={handleEventProps1}
...etc...
onEventProps9={handleEventProps9}
/>
It doesn't have clean code and maintaining or reading the code is a disaster for me. So what is the most efficient way in my case to improve aesthetic for component props?
First, I strongly suggest you do not pass a lot of props simply because you make things more complex. But if you did that the solution I have is to first create an object. The keys of that Object would be the name of the props you have and the values would be the values you want to pass as your props. and then pass that object to your component. It would be basically something like this:
const propObject = {
firstProp: firstValue,
secondProp: secondValue,
...}
<Component {...propObject} />
You can use this method to pass your props in a cleaner way.
I still don't get why we need a prop(s) in react, seriously. Why can't we just declare everything we need as an argument or parameter in the child component, then declare it, why do we have to declare it in a parent element then pass the props to the child component then catch it. I don't understand why. It seems a bit confusing, I'm yet to see the why in it
Props are useful in the case that you have a controller in the parent component and you want to pass the value of that controller to the child to make a certain action. The replacement for props would be to store everything globally in redux or mobx, but that needs much work. for example
const ParentComponent = () =>{
const [flag, setFlag] = useState(false)
return(
<div>
<button onClick={()=>setFlag(!flag)}>click me!</button>
<ChildComponent flagValue={flag}/>
</div>
)
}
as in the example for some reason the button that changes the flag is in the parent and you need to use that value in the ChildComponent. So here you benefit a lot from using props.
Also in writing a cleaner code and drier one so as not to repeat the same values in different react components
You might not be familiar with React if you ask such questions (no anger at all). It's one of the main concepts of the React library.
You can easily split a huge component into smaller pieces. But then, you need to provide the same data here and there. To prevent repeating yourself (DRY - don't repeat yourself), you can share the prop with many child components.
If you are interested in React - check the documentation.
It's one of the prettiest documentation I've ever read.
prop changes trigger UI re-render for the child component.
That's one of the props of using props.
When passing props down into a React component I am currently of doing this:
<MyComponent
{...this.props}
foo=foo
bar=bar
/>
foo and bar are props that I know MyComponent will need. However, in most cases MyComponent also has components within it that need props from higher components, hence I use the {...this.props} operator to pass them forward. Should I be doing this, or should I be listing out exactly the props that the child components of MyComponent will need?
You should use a state management like Flux, Redux or Mobx (i think, haven't used Mobx at all) to combat this problem of passing props through multiple levels without the intermediate components needing them.
You should be passing only the props exactly needed down to the child. I read a great post on github about this but can't find it.
It's just hard to manage when your app grows and it's really an abuse of the Es6 spread syntax operator (i.e it makes it easy short term to pass props down, but long term you still have the problem, you are just masking it). Not sure if it slows down application but it will re-render all child components again if the prop changed which is unnecessary.
For example when using Redux you can "connect" components to a global state (think databases) and pass them through as props for whichever components you want and bypass components having to forward props to child components.
It's hard at first to learn but 1000% worth it.
You should pass in only the props needed, or implement a container component that only passes in the props needed. Or you can implement shouldComponentUpdate on your component. The easiest way to get performance is to only pass in the required props though.
Lets say I have the following code:
<View>
<ComponentA>
<TouchableHighLight onPress={this.refs.componentB.foo.bind(this)}><Text>Hey</Text></TouchableHighLight>
</ComponentA>
<ComponentB ref='componentB'>
....
</ComponentB>
</View>
-
class ComponentB extends React.Component = {
foo() {
// do something
}
}
The ref for componentB will be undefined when I try to use it in ComponentA. Im guessing it's because i ComponentA tries to use it before the ref is assigned.
Whats the best way to fix this?
I could have all the functions in the parent component, but it will end up being a huge file if I dont separate it filled with functions that IMO should be contained in the child components.
You could wrap the onPress-handler in a function:
<TouchableHighLight onPress={() => this.refs.componentB.foo()}>
You cannot access any method in <Component B> from <Component A>. This is by design, done on purpose, and for your own good :)
Best to stick to react design principles, and not try to make a shortcut. You will definitely regret any shortcuts later on.
And BTW: A ref is a reference to the mounted component in the DOM, not to the react component. So I don't think you could get it to work anyway. Besides, I would always advise anybody not to use refs, ever (I learned that from a Netflix talk on react).
One way to fix:
Put a doFooInB boolean in state inside your parent <View> component
Pass this doFooInB to <Component B> as a prop.
<Component B> reads the prop, and responds accordingly (with an internal function called from B's render)
Define an onPress event inside parent <View> component and pass function as prop to component A.
onPress simply needs to setState({ doFooInB : true }) or something to trigger re-render, which will trigger the method in component B.
Yes, this is more code, but it really is better than creating some shortcut.
I don't see a problem in having these shared functions in a parent component, using props to call them when something happens in one of the children.
That's actually an encouraged React pattern, because you make your children components easier to test.
If you make ChildA aware of ChildB, you are coupling them instead of having the parent to just coordinate them.
See also this:
https://facebook.github.io/react/docs/more-about-refs.html#cautions
If you have not programmed several apps with React, your first inclination is usually going to be to try to use refs to "make things happen" in your app. If this is the case, take a moment and think more critically about where state should be owned in the component hierarchy. Often, it becomes clear that the proper place to "own" that state is at a higher level in the hierarchy. Placing the state there often eliminates any desire to use refs to "make things happen" – instead, the data flow will usually accomplish your goal.
It's not better idea to give ref to component since ref can be done on DOM objects. so, the better solution is to make function in parent component and pass that function as props to child component in onPress() handler of child component call that method as this.props.method which will automatically call the parent component method. In this way parent component method can be executed successfully.
<ComponentA>
constructor(){
this.method = this.methodA().bind(this);
}
methodA(){
}
<ComponentA method=this.methodA/>
<ComponentB>
<TouchableHighlight onPress={()=>{this.props.method}}>
</ComponentB>
I just checked out HOC's in React. They are pretty cool. However, doesn't simply wrapping a component achieve the same result?
Higher Order Component
This simple HOC passes state as properties to the ComposedComponent
const HOC = ComposedComponent => class extends React.Component {
... lifecycle, state, etc;...
render() {
return (<ComposedComponent {...this.state} />);
}
}
Component Wrapping
This component passes state as properties to the child component
class ParentComponent extends React.Component {
... lifecycle, state, etc;...
render() {
return (
<div>
{React.cloneElement(this.props.children, { ...this.state })}
</div>
);
}
}
Although usage is slightly different between the two, they both seem to be equally as reusable.
Where is the real difference between HOC's and composing components via this.props.children? Are there examples where you can only use one or the other? It is a better practice to use HOC's. Are these just choices that you have where you get to pick your preferred flavor?
Higher-Order Components (HOC) and Container Components are different. They have different use cases and solve similar, but different problems.
HOC are like mixins. They are used to compose functionality that the decorated component is aware of. This is opposed to Container Components that wrap children and allow the children to be dumb (or not aware of the Container's decorated functionality).
It is true when transferring props, that Containers can add functionality to their children. But, this is usually in the form of props being passed down to the children. In Containers, this is also awkward because of the limitation that you cannot simply add props to an already created Element:
So, if you wanted to add a new prop to a child from this.props.children, you would have to use cloneElement. This is not as efficient because it means you have to re-create the elements.
Also, HOC is simply a way (factory) for creating Components. So, this can happen outside the render.
I just wanted to add that when you need to dynamic higher order components the Container approach works better.
If you e.g have 4 elements to render that could have a HOC defined, you would like to create the Higher Order Component inside render, but since calling higher order components inside render causes the <HigherOrderComponent/>'s to remount on every render this becomes a very bad Idea.
This is documented here; https://github.com/facebook/react/blob/044015760883d03f060301a15beef17909abbf71/docs/docs/higher-order-components.md#dont-use-hocs-inside-the-render-method.
But in general I would go for the HOC approach.