I'm a bit new in React, so my question is regarding a best practice on something i'm trying to do. I might not being "thinking react" so I need your help.
I'm involved with a really big project related to sports. To minimise the number of ponents I need to create, I'm trying to use one single ponent to deal with multiple sports.
I will try to draw a basic scenario where it will match with a similar thing i'm trying to do.
-----------------------------------
| module: Scoreboard |
| |
| ----------------------------- |
| | module: scores | |
| | Sydney 1 x 0 Melbourne | |
| ----------------------------- |
| |
| ----------------------------- |
| | module: results | |
| ----------------------------- |
| |
| ----------------------------- |
| | module: Footer | |
| ----------------------------- |
| |
-----------------------------------
With this scenario in mind, mind that all the props gets loaded when the ponent is loaded or through a parent.
I have 2 things that i need to do here on my script.
1 - Only display the ponent footer if there is a footer which is represented by this.props.footer 2 - Only display the ponent results if there is results which is represented by this.props.results
Right now i have a few user cases that I can do here.
On my render method I can do something like (don't mind the {...this.props} i only put there to represent i'm passing variables)
Case 1:
render: function() {
var results, footer;
if (this.props.results) {
results = (<results {...this.props} />)
}
if (this.props.footer) {
results = (<footer {...this.props} />)
}
return (
<div class="scoreboard">
<scores {...this.props} />
{results}
{footer}
</div>
);
}
The downside I see here is the amount of ifs inside the render. Not very readable, specially if we have a bit more than 2 ponents that does the same thing
Case 2:
render: function() {
return (
<div class="scoreboard">
<scores {...this.props} />
{this.props.results ? <results {...this.props} /> : ''}
{this.props.footer ? <footer {...this.props} /> : ''}
</div>
);
}
Although I like this case better, Sometimes I have ponents that takes a big number of properties which can get to the same problem above (readability). Bare in mind i'm using {...this.props} to simplify the example
Which is the case I like better. Putting all the logic inside it's own ponent.
The problem is that I don't know how to stop the first render. And I also don't want to put a "display: block" on the page avoiding to add unnecessary markup where is not needed, so my idea here is really do not render the ponent at all if it's not needed. If i'm doing it wrong, or this is an anti-pattern, i would like some insight of it, like i said, i'm new with all of this react stuff, any ment is wele.
So basically, like I said, I can't stop it from rendering.
Lets take the results ponent for instance, and lets there is a table and there is about about 10 lines of markup in it. Let's draw a case:
On my render method I can do something like
module: SCOREBOARD
render: function() {
return (
<div class="scoreboard">
<scores {...this.props} />
<results {...this.props} isVisible={this.props.results} />
<footer {...this.props} isVisible={this.props.footer} />
</div>
);
}
module: RESULTS
render: function() {
return this.props.isVisible ? (
<div class="results">
<table>
....
</table>
</div>
) : null;
}
I would control the return of the render with a property isVisible. Defaulting it to always false. Haven't found a good article about it, but i'm assuming this is not an elegant way.
I know we have a shouldComponentUpdate, but this won't stop the first render on the page, which will display some of the tables in our examples.
I wonder if anyone has some insight, a valid argument, or a solution to do what I'm trying to do. Remember that It's a big project, so I'm trying to avoid to create hundreds of ponents and instead having to use one ponent where there are a few variables that I could or not display the ponent on the page.
I'm a bit new in React, so my question is regarding a best practice on something i'm trying to do. I might not being "thinking react" so I need your help.
I'm involved with a really big project related to sports. To minimise the number of ponents I need to create, I'm trying to use one single ponent to deal with multiple sports.
I will try to draw a basic scenario where it will match with a similar thing i'm trying to do.
-----------------------------------
| module: Scoreboard |
| |
| ----------------------------- |
| | module: scores | |
| | Sydney 1 x 0 Melbourne | |
| ----------------------------- |
| |
| ----------------------------- |
| | module: results | |
| ----------------------------- |
| |
| ----------------------------- |
| | module: Footer | |
| ----------------------------- |
| |
-----------------------------------
With this scenario in mind, mind that all the props gets loaded when the ponent is loaded or through a parent.
I have 2 things that i need to do here on my script.
1 - Only display the ponent footer if there is a footer which is represented by this.props.footer 2 - Only display the ponent results if there is results which is represented by this.props.results
Right now i have a few user cases that I can do here.
On my render method I can do something like (don't mind the {...this.props} i only put there to represent i'm passing variables)
Case 1:
render: function() {
var results, footer;
if (this.props.results) {
results = (<results {...this.props} />)
}
if (this.props.footer) {
results = (<footer {...this.props} />)
}
return (
<div class="scoreboard">
<scores {...this.props} />
{results}
{footer}
</div>
);
}
The downside I see here is the amount of ifs inside the render. Not very readable, specially if we have a bit more than 2 ponents that does the same thing
Case 2:
render: function() {
return (
<div class="scoreboard">
<scores {...this.props} />
{this.props.results ? <results {...this.props} /> : ''}
{this.props.footer ? <footer {...this.props} /> : ''}
</div>
);
}
Although I like this case better, Sometimes I have ponents that takes a big number of properties which can get to the same problem above (readability). Bare in mind i'm using {...this.props} to simplify the example
Which is the case I like better. Putting all the logic inside it's own ponent.
The problem is that I don't know how to stop the first render. And I also don't want to put a "display: block" on the page avoiding to add unnecessary markup where is not needed, so my idea here is really do not render the ponent at all if it's not needed. If i'm doing it wrong, or this is an anti-pattern, i would like some insight of it, like i said, i'm new with all of this react stuff, any ment is wele.
So basically, like I said, I can't stop it from rendering.
Lets take the results ponent for instance, and lets there is a table and there is about about 10 lines of markup in it. Let's draw a case:
On my render method I can do something like
module: SCOREBOARD
render: function() {
return (
<div class="scoreboard">
<scores {...this.props} />
<results {...this.props} isVisible={this.props.results} />
<footer {...this.props} isVisible={this.props.footer} />
</div>
);
}
module: RESULTS
render: function() {
return this.props.isVisible ? (
<div class="results">
<table>
....
</table>
</div>
) : null;
}
I would control the return of the render with a property isVisible. Defaulting it to always false. Haven't found a good article about it, but i'm assuming this is not an elegant way.
I know we have a shouldComponentUpdate, but this won't stop the first render on the page, which will display some of the tables in our examples.
I wonder if anyone has some insight, a valid argument, or a solution to do what I'm trying to do. Remember that It's a big project, so I'm trying to avoid to create hundreds of ponents and instead having to use one ponent where there are a few variables that I could or not display the ponent on the page.
!!this.props.results && results()
– iofjuupasli
Commented
Sep 1, 2015 at 15:03
If you have this:
render: function() {
return (
<div class="scoreboard">
<scores {...this.props} />
{this.props.results ? <results {...this.props} /> : ''}
{this.props.footer ? <footer {...this.props} /> : ''}
</div>
);
}
You can rewrite it as different methods:
render: function() {
return (
<div class="scoreboard">
<scores {...this.props} />
{this.props.results ? this.renderResults() : ''}
{this.props.footer ? this.renderFooter() : ''}
</div>
);
},
renderResults(){
return (
<results {...this.props} />
);
},
renderFooter(){
return (
<footer {...this.props} />
);
},
This way the conditional part never gets larger with more props, but you can still have that sub-render with the full thing.
To minimise the number of ponents I need to create, I'm trying to use one single ponent to deal with multiple sports
Having a lot of ponents isn't bad. You can have a lot of tiny ponents. When deciding the boundaries think about these (in terms of requirements changing tomorrow).
For siblings (multiple ponents with similar api, not nested):
For parent/child:
avoiding to add unnecessary markup
Having unnecessary markup is something that happens often in react. It's a tradeoff, but doesn't usually cause problems.
I would control the return of the render with a property isVisible
This is an anti-pattern. Unless you did this in every ponent, you're making assumptions about the user of the ponent which makes your code less modular and more difficult to maintain. Do conditional rendering in the parent unless you have a good reason to do otherwise.
I do it this way;
module: RESULTS
render: function() {
if (this.props.hide) return null;
return (
<div class="results">
<table>
....
</table>
</div>
);
}
Its a good pattern for clarity and performance.
If the only thing u want to do is not show, the footer and results when they are visible, go for solution one. Even though solution 2 is shorter, solution one is still better for readability,
it seems like ur looking for a way, to remove if statements ,in order to reduce code though as u can see in solution three, it just leads to code plexity.
I don't know what other props u are passing to the footer / results, but for this specific case, the if statement is the best way to go.
[shouldComponentUpdate]
Invoked before rendering when new props or state are being received. This method is not called for the initial render or when forceUpdate is used. (facebook docs)
-U can use this to for example do a (shallow) pare between the old and new props, and return true, when to render and false when not to render, (but this will only be triggered on update), its has to has old values first (as u described)
[ponentWillReceiveProps]
invoked when a ponent is receiving new props. This method is not called for the initial render.
Use this as an opportunity to react to a prop transition before render() is called by updating the state using this.setState(). The old props can be accessed via this.props. Calling this.setState() within this function will not trigger an additional render. (facebook)
-U could do some magic, here when the ponent receives props, u could decide to do this.setState({ isVisible: false }); and then in your render check for isVisible: false, and don't show its content, and later update this state. But you don't want to have "state" living in your ponents
you could also just pass a prop to the ponent, ponent visible={false} and then check for this.props.visible , within the subponent, but u are just moving the if statements
But this is not the way it is supposed to work, the idea of the unidirectional data flow (top down) with the react lifecycle is that a change is triggered from above, u should not stop the render, if props is passed to its child ponent its should re-render -> if u wish to stop the render, u should do it in shouldponent update only if the data did not change, (take a look at immutable js (and purerender)) ,
But for this case just use the if statement.
I also would like to suggest for you to take a look at higher level ponents, http://browniefed./blog/2015/05/02/react/ (also read the mixis are dead, long live position link within it)
The React documentation has a whole page on conditional rendering. If you are looking for best practice, I would start there. For short and single-line elements, I personally like the terseness of using the logical && operator. It would look a lot like your Case 2:
render: function() {
return (
<div class="scoreboard">
<scores {...this.props} />
{this.props.results && <results {...this.props} />}
{this.props.footer && <footer {...this.props} />}
</div>
);
}