'ReactJS Functional Component vs Component Functions for conditional rendering
Sometimes I want to move my conditional rendering out of render()
, and I always have dilemma between these two approaches:
class MyComponent extends React.Component {
_renderSomething() => {
const {x, y, z} = this.props
// conditional rendering based on props
}
render() {
return (
{ this._renderSomething }
// vs
{ renderSomething(this.props) }
// which one is better?
)
}
}
const renderSomething = (props) => {
const {x, y, z} = props
// conditional rendering based on props
}
export default MyComponent
Any performance difference between _renderSomething
and this.renderSomething
?
When should I use which?
Solution 1:[1]
There is a performance penalty with Functional Components vs Functions returning elements. An example would be this -
// Component approach
let Tab = ({label, link}) => <li><a href={link}>{label}</a></li>;
class Tabs extends Component {
render(){
return (
// notice the key prop is handled by parent render
<ul>{this.props.tabs.map(tab => <Tab {...tab} key={link}>)}</ul>
)
}
}
// function based approach, notice the key prop is handled by the function
let tab = ({label, link}) => <li key={link}><a href={link}>{label}</a></li>;
class Tabs extends Component {
render(){
return (
<ul>{this.props.tabs.map(item => tab(item))}</ul>
)
}
}
In Component example, you will end up with unnecessary intermediate Tab
components, which will add to the virtual dom, however small they are. And then as they grow, these components will eventually cause slow renders. React will need to keep track of these components over subsequent renders. And these being functional components, you would not have access to shouldComponentUpdate
based optimizations.
The function version will not suffer from this as it returns Elements
directly, instead of components. Also, with smaller functions, there will be gains due to code inlining.
An extended discussion into this approach is here.
Solution 2:[2]
in general, a stateless component should probably be a pure function that just returns the component to render
Below, you could replace <EmptyList />
with <ul></ul>
but the idea is you can abstract wherever you feel is necessary – in this case, I thought it would be nice to have some placeholder text for empty lists, so making it a stateless functional component was an easy choice
So little of your app actually needs state – in fact, you should be striving to remove it wherever possible. When nothing needs state, everything can be expressed with functions
const EmptyList = ({ placeholder = "There are no items to display" }) =>
<ul><li>{ placeholder }</li></ul>
const ListItem = ({ text = "" }) =>
<li>{ text }</li>
const List = ({ items = [] }) =>
items.length === 0
? <EmptyList />
: <ul>{ items.map (text => <ListItem text={text} />) }</ul>
ReactDOM.render(<List items={[1,2,3]} />, document.querySelector('#list1'))
ReactDOM.render(<List items={[]} />, document.querySelector('#list2'))
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react-dom.min.js"></script>
<div id="list1"></div>
<div id="list2"></div>
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
Solution | Source |
---|---|
Solution 1 | darksoulsong |
Solution 2 |