React Native Render Method Being Called 3-5x - reactjs

I am fairly new to React and React Native and am trying to keep performance in mind as Im working with it.
I read somewhere that it was a good idea to put a console.log(...) into the render(...) method of my components so that I can see how often they were being rendered.
I did this for one of my first screens the user sees and I noticed it was rendering 3 to 4 times right away.
The code for this method is defined below, and does nothing but render 3 sections.
Is there anything in the code below that is being done incorrectly or in a non performant way that I should be doing differently? For example, I read in several places that the way I am binding my callbacks is not correct and will register multiple times (each time render is done).
Also, is it alright or normal for the render(...) to be done multiple times or can it be avoided?
class Home extends Component {
_onRequestItemClick(id){
alert(id);
}
_onMakeRequestClick(){
this.props.dispatch(navigatePush('Create Request'));
}
render() {
console.log('Rendering Home...');
return (
<View style={styles.container}>
<View style={[styles.base,styles.halfHeight]}>
{this._renderRequestList()}
</View>
<View style={[styles.base,styles.quarterHeight]}>
{this._renderMakeRequestButton()}
</View>
<View style={[styles.quarterHeight]}>
{this._renderFulfillmentScroller()}
</View>
</View>
);
}
_renderRequestList(){
let { requests } = this.props;
return (
<RequestList
requests={requests}
onRequestItemClick={this._onRequestItemClick.bind(this)}
/>
);
}
_renderMakeRequestButton(){
return (
<ActionButton
title="Make Request"
onActionPress={this._onMakeRequestClick.bind(this)}
/>
);
}
_renderFulfillmentScroller(){
let { fulfillments } = this.props;
var onPressItem = (item)=> alert('item selected:' + item.id);
return (
<CalendarBlockScrollView
bounces={false}
style={styles.scroller}
itemStyle={styles.fulfillment}
items={fulfillments}
onPressItem={onPressItem}
/>
);
}
}
function mapDispatchToProps(dispatch) {
return {
dispatch
};
}
function mapStateToProps(state) {
return {
userId:state.get('profile').current.id,
requests:state.get('requests').all.requests,
fulfillments: state.get('fulfillments').all.fulfillments
}
}
export default connect(mapStateToProps,mapDispatchToProps)(Home);

Unless I'm missing something, this piece of code seems ok. Maybe it's the component that calls this one that's resulting the multiple renders?
I can give you a few suggestions:
Try replacing render with:
render() {
console.log('Rendering Home...');
return (<View />);
}
and check whether the component is rendered multiple times. If it doesn't then try adding another piece each time until you find the problem. If it does then it's not the problem with this component. It the parent component that's causing this.
like you said, binds are very expensive. so binding every render is a bad idea. you can either bind in construction time or use arrow function:
constructor() {
this._onRequestItemClick = this._onRequestItemClick.bind(this);
}
_renderMakeRequestButton(){
return (
<ActionButton
title="Make Request"
onActionPress={(event) => this._onMakeRequestClick(event)}
/>
);
}
console.log is an expensive, make sure you remove it when going to production.
mapDispatchToProps is redundant. you can just remove it.
You can read more about react-native performance here

Related

How to solve Error: Maximum update depth exceeded?

I started learning React Native 2 weeks ago and I got at the installing plugins chapter. I installed react-native-popover-view and I don't know but for me I get the error:
Maximum update depth exceeded. This can happen when a component repeatedly calls setState inside componentWillUpdate or componentDidUpdate. React limits the number of nested updates to prevent infinite loops.
I searched around and after staying 2 days on this I understood that I have setState in render(), because I have the Modal in App render(). I tried to figure out how to change it, but without success.
So I have the Modal.js class:
class Modal extends Component {
state = {
isVisible: true
}
closePopover() {
this.setState({ isVisible: false });
}
render() {
return (
<View >
<Popover
isVisible={this.state.isVisible}
fromView={this.touchable}
onRequestClose={() => this.closePopover()}>
<View style={styles.closeXContainer}>
<Image source={closeX} style={styles.closeX} onPress={this.closePopover()} />
</View>
<Text>I'm the content of this popover!</Text>
</Popover>
</View>
);
}
}
and in the App.js, when the page loads, the modal should start first, covering the App.js component, that could be seen on the back.
class App extends Component {
render() {
return (
<View style={styles.container}>
<Modal />
</View>
);
}
}
Someone can please help with this? How the code should be to not get that error anymore?
This error is due to when you call onPress={this.closePopover()} on Image , it calls the function and causes the app to re-render which again causes function to be invoked, and hence an infinite loop. The best way would be calling it directly without parentheses onPress={this.closePopover} or create an anonymous function onPress={() => this.closePopover()}, which gets executed only once
your problem is in the call of the function this.closePopover() in order to fix it, you only need to change it to:
class Modal extends Component {
state = {
isVisible: true
}
closePopover() {
this.setState({ isVisible: false });
}
render() {
return (
<View >
<Popover
isVisible={this.state.isVisible}
fromView={this.touchable}
onRequestClose={this.closePopover}>
<View style={styles.closeXContainer}>
<Image source={closeX} style={styles.closeX} onPress={this.closePopover} />
</View>
<Text>I'm the content of this popover!</Text>
</Popover>
</View>
);
}
}
Hope this help.

Early returns in React sub render function: return null, [], or React.Fragment?

Let's say I have a simple component that may or may not render a Counter.
What's the best practice in React to express a blocked code path? Should it return null, [], or a Fragment?
class App extends Component {
renderCounter() {
if (!this.props.shouldRenderCounter) {
// // which should I return?
// return;
// return null;
// return [];
// return <React.Fragment />;
}
return <Counter />;
}
render() {
return (
<div>
{this.renderCounter()}
</div>
);
}
}
I think null is the clearest, but I can imagine it causing problems if the context around the return function expects a component. [] and Fragment both seem like fine options to me, except Fragment is a little easier to read. What's the difference?
Returning null is recommended by the React team:
In rare cases you might want a component to hide itself even though it was rendered by another component. To do this return null instead of its render output.
You dont need to create an extra function for it.
This will do the job:
class App extends Component {
render() {
return (
<div>
{this.props.shouldRenderCounter && <Counter />}
</div>
);
}
}

Is it safe to pass a component props called "children"?

Can I pass children={someArray} as props to a component without muddling the namespace for props.children? I've tried it, and I'm actually surprised it doesn't seem to break anything. Still, it seems like a very bad idea. Should I be concerned about potential collisions down the road, or does React protect against this somehow?
For context, I'm writing a HOC for creating an accordion-style row in a list, and I want to keep the props it passes down as simple and generic as possible, for the sake of reuse. The parent/children paradigm just seems the most intuitive.
Here's a simplified version:
function ProductList(props) {
return (
<List>
{props.products.map(product => (
<ProductWithVarieties parent={product} children={product.varieties} key={item.id} />
))}
</List>
)
}
function withChildren(ParentComponent, ChildComponent) {
return class extends React.Component {
// OMMITTED: a constructor, some life cycle hooks, event handlers, etc.
render(props) {
const renderChildren = () => {
return this.props.children.map(child => {
return <ChildComponent {...child} key={child.id}/>
})
}
return (
<div>
<ParentComponent
{...this.props.parent}
onClick={this.toggleChildren}
hasChildren={this.props.children.length > 0} />
{ this.state.showChildren ? renderChildren() : null }
</div>
)
}
}
}
const ProductWithVarieties = withChildren(ProductComponent, VarietyComponent)
It is "safe" to pass it as children prop, but from standardswise you shouldn't do it and rather call it something different

Will using functions to render content hurt react performance?

This article (and other places) mention now calling functions inside of render:
https://levelup.gitconnected.com/optimize-react-performance-c1a491ed9c36?ref=reddit
I've always used a pattern for large React class components where I'll move some of the JSX out of the render function into methods. This avoids having a billion little one-time-use separate components and it also avoids having to put lengthy if/then or ternary logic inside of a render area which I find slightly harder to read.
class HelpModal extends React.Component {
state = { visible: false };
renderContent = () => {
if (this) {
return <div />
}
if (that) {
return <span />
}
}
render() {
return (
<Modal visible={this.state.visible}>
{this.renderContent()}
</Modal>
);
}
}
I've seen this strategy in a bunch of places, but now it sounds like, based on the above blog post, that this may be a bad practice performance-wise?
It depends on how you use inline functions.
React calls the render function after props and/or state changes. Each time they change the render function is called.
If you compute things that haven't changed because of the new props/state values then this inline function has indeed a negative impact on your app's performance.
Example:
render() {
<div>
{ this.props.items.map(() => <SomeComponent />) }
</div>
}
If you compute it here or anywhere else doesn't change the fact that you need to compute it each time the render function is called. No negative effect at all.
computeStaticStuff(x, y) {
return x + y > 0 ? <p /> : <i />;
}
render() {
<div>
{ () => this.computeStaticStuff(5, 6) }
</div>
}
This would be a ((n) extremely stupid) example of recomputation that is not needed at all.

react component lifecycle to execute before render

I want to have some check before react component is rendered..
Lets say I have a component which renders something like
render() {
const {videos, actions} = this.props
return (
<div>
<List />
</div>
)
}
But before rendering the list I want to have custom check on the list...
What I meant to say is before showing the <List /> component I want to have some check and only after that check is finished I want to show the component with render method ..
The check I am mentioning here might be anything like the list should be 10 in count or anything.
I have tried following
componentWillUpdate(){
console.log("Component will update")
}
shouldComponentUpdate(){
console.log("Should component update")
}
From the react documentation I knew that both of them are called before render... But when I do this nothing is printed in the console but render method is called..
I know that componentWillMount() is called before render but what I want is a function which calls render only after the completion or return from the function
Hope you understand and need help
In the render() function you can run checks before you return the JSX/elements:
render() {
// run any checks here
const {videos, actions} = this.props
return (
<div>
<List />
</div>
)
}
You can return early from render with a different result. When the props change, render will be called again with newer props.
class MyComponent {
render() {
const { items } = this.props;
if (items.length < 10) return <span>Loading...</span>;
return <List items={items} />;
}
}

Resources