I'm developing a React Native application (although I think my issue applies to React in general) made of multiple screens.
So I've created a simple ponent to switch the screens:
import React, { Component } from 'react';
import { connect } from 'react-redux'
import { View } from 'react-native';
class AppNavComponent extends Component {
constructor() {
super();
this.screenCache_ = {};
}
render() {
if (!this.props.route) throw new Error('Route must not be null');
let route = this.props.route;
if (this.screenCache_[route.routeName]) return this.screenCache_[route.routeName];
let Screen = this.props.screens[route.routeName].screen;
this.screenCache_[route.routeName] = (
<View>
<Screen/>
</View>
);
return this.screenCache_[route.routeName];
}
}
const AppNav = connect(
(state) => {
return {
route: state.route,
};
}
)(AppNavComponent)
export { AppNav };
this.props.screens
contains the list of screens, and this.props.route
the route that needs to be displayed. The ponent works fine, but my problem is that I'd like to cache to memory certain screens because they are slow to render (a large list) and they lose the scrolling position whenever React re-render them.
In the example above, I've tried to save the rendering to this.screenCache_
but that's probably not the right approach as the screens are still re-rendering when I load them, go to another page, and go back to them.
I guess that's a mon problem but I can't find any information on Google. Any suggestion on how to do this?
I'm developing a React Native application (although I think my issue applies to React in general) made of multiple screens.
So I've created a simple ponent to switch the screens:
import React, { Component } from 'react';
import { connect } from 'react-redux'
import { View } from 'react-native';
class AppNavComponent extends Component {
constructor() {
super();
this.screenCache_ = {};
}
render() {
if (!this.props.route) throw new Error('Route must not be null');
let route = this.props.route;
if (this.screenCache_[route.routeName]) return this.screenCache_[route.routeName];
let Screen = this.props.screens[route.routeName].screen;
this.screenCache_[route.routeName] = (
<View>
<Screen/>
</View>
);
return this.screenCache_[route.routeName];
}
}
const AppNav = connect(
(state) => {
return {
route: state.route,
};
}
)(AppNavComponent)
export { AppNav };
this.props.screens
contains the list of screens, and this.props.route
the route that needs to be displayed. The ponent works fine, but my problem is that I'd like to cache to memory certain screens because they are slow to render (a large list) and they lose the scrolling position whenever React re-render them.
In the example above, I've tried to save the rendering to this.screenCache_
but that's probably not the right approach as the screens are still re-rendering when I load them, go to another page, and go back to them.
I guess that's a mon problem but I can't find any information on Google. Any suggestion on how to do this?
Share Improve this question asked Jul 14, 2017 at 21:36 laurentlaurent 91k83 gold badges310 silver badges442 bronze badges3 Answers
Reset to default 6There's no way to efficiently cache the ponent in the way you go about it, because the DOM still would need to repaint it later, which is the heavy part.
A simpler solution, and I think slack does that under the hood, is to use display: none
instead.
<View style={shouldDisplayScreen ? {} : { display: none }} />
PS. You might want to set shouldComponentUpdate
to false
, if the ponent is currently not being displayed to avoid performance issues.
Your first answer shouldn't be to cache things in React. There are a lot of other ways to increase performance. Start by reading the performance section of their documentation. There are some very simple solutions to increase performance right off the bat.
React Native Documentation: Performance
Some other things you can do to increase performance:
- Remove the console.logs and other loggers.
- Use ponentShouldUpdate to ensure that you only re-render when you need to.
- If you are using redux take a look at Selectors. If you have data that needs to be calculated and you are doing needless repetitive calculations, you can memoize that data.
I think that your problem es from something from the React Native docs so run through those things first before trying to do things overly plicated.
For a point of reference, one of my buddies recently made a VR application doing multiple calculations that updated redux state every time the gyroscope moved and rerendered objects on the DOM hundreds of times per second. React Native can take a lot so don't worry about caching yet.
Sounds like you need a navigation library to handle screens. Check https://reactnavigation
For example, use a StackNavigator with two routes, i.e. list and detail.
const app = StackNavigator({
Index: { screen: Some list view },
Detail: { screen: some detail page },
});
Also if the ListView is slow for you, try the new FlatList or SectionList ponent that’s available since 0.43. They are more performant.