Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to save a rendered component to memory?

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 component 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 component 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 common problem but I can't find any information on Google. Any suggestion on how to do this?

like image 229
laurent Avatar asked Jul 14 '17 21:07

laurent


2 Answers

There's no way to efficiently cache the component 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 component is currently not being displayed to avoid performance issues.

like image 136
Lyubomir Avatar answered Sep 29 '22 02:09

Lyubomir


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:

  1. Remove the console.logs and other loggers.
  2. Use componentShouldUpdate to ensure that you only re-render when you need to.
  3. 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 comes from something from the React Native docs so run through those things first before trying to do things overly complicated.

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.

like image 37
EJ Mason Avatar answered Sep 29 '22 00:09

EJ Mason