What causes the frustratingly slow transition between two components on Android?

I am currently in the process of developing a compact puzzle app that resembles a crossword using Expo, React Native, and Typescript.

Below is a concise version of the PuzzleMain component:

const PuzzleMain: React.FC<PuzzleMainProps> = ({ navigation }) => {
    let puzzle: AcrosticPuzzleData = parseAcrosticPuzzle(PUZZLE_TEXT);

    const grid = <PuzzleGrid puzzle={puzzle} />;
    const clueView = <PuzzleCluesView puzzle={puzzle} />;

    const [index, setIndex] = React.useState(0);

    return <View style={styles.container}>
        {index == 0 ? grid : clueView}
        <View style={styles.keyboardContainer}>
            <Button onPress={() => setIndex(index == 1 ? 0 : 1)} title={"See " + routes[index == 0 ? "Grid" : "Clues"].key} />
            <Keyboard />
        </View>
    </View>;
}

In summary, there are components for the "grid" and "clues," and a button allows users to switch between them.

When tapping this button, it takes approximately 3 seconds for the change to occur on my Pixel 5 test device. This delay does not occur when testing on web using Expo, so it may be specific to Android devices?

Here are some troubleshooting steps I have taken:

  1. Memoizing the PuzzleGrid and PuzzleCluesView components (
    const PuzzleGrid: React.FC<Props> = memo(({ puzzle }) ...
    . However, this did not significantly improve performance. There were no console logs from a custom puzzle comparator used in the memo function, indicating re-rendering may not be the issue.
  2. Utilizing TabView to swipe between components instead - this approach yielded better results. Nonetheless, I prefer having both options available, and adding the button to the TabView implementation resulted in similar delays.
  3. Running npx expo start --no-dev and building an apk for installation - while this method showed faster loading times, there was still a noticeable delay of about a second or two, which is considered too slow.

Answer №1

It appears that you are implementing conditional rendering, which means the entire component is re-created whenever the condition changes. This can slow down rendering depending on the complexity of your component.

Why isn't memoization working? Memoization is an optimization technique, but it doesn't always guarantee improved performance.

To improve loading speed, consider the following:

  1. Optimize the internal logic of PuzzleGrid and PuzzleCluesView, ensuring that sub-components that receive duplicate props are wrapped in memo and heavy items are loaded asynchronously using a loader.
  2. Utilize InteractionManager to enhance loading speed and display loaders without causing UI freeze.
  3. Instead of unmounting components, overlap them and manage visibility using InteractionManager to prevent unnecessary unmounting and slowdowns when rendering heavy components simultaneously.

Rather than just using {index == 0 ? grid : clueView}, consider implementing something like

<View>
    {grid}
    <View
      style={{
        // Specify height and necessary properties for visibility
        position: 'absolute',
        display: index == 0 ? 'none' : 'flex',
      }}>
      {clueView}
    </View>
</View>

I reviewed your code snippet and made updates to PuzzleMain.tsx

const PuzzleMain: React.FC<PuzzleMainProps> = ({ puzzle }) => {
  ...
  const [showClues, setShowClues] = useState(false);
  return (
    <View style={styles.container}>
      <View style={{ flex: 1 }}>
        {grid}
        <View
          style={{
            display: showClues ? "flex" : "none",
            position: "absolute",
            height: "100%",
            width: "100%",
            backgroundColor: "#fff",
          }}
        >
          {clueView}
        </View>
      </View>
      <Button
        onPress={() => setShowClues(!showClues)}
        title={`See ${showClues ? "Cues" : "Grid"}`}
      />
    </View>
  );
};

Added a screen recording to showcase the improved performance!

https://i.sstatic.net/N7KKk.gif

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

What could be the reason for the malfunction of this setter function?

Trying to obtain a variable and then utilize a setter method to set another variable. The code in question: if(savedInstanceState != null) { mCurrentIndex = savedInstanceState.getInt(KEY_INDEX); mIsCheater = savedInstanceState.getBoolean(KEY_CHEA ...

The issue lies with the Cookies.get function, as the Typescript narrowing feature does not

Struggling with types in TypeScript while trying to parse a cookie item using js-cookie: // the item 'number' contains a javascript number (ex:5) let n:number if(typeof Cookies.get('number')!== 'undefined'){ n = JSON.pars ...

Pay attention to the input field once the hidden attribute is toggled off

In attempting to shift my attention to the input element following a click on the edit button, I designed the code below. The purpose of the edit is to change the hidden attribute to false. Here's what I attempted: editMyLink(i, currentState) { ...

Encountering an error when attempting to add the 'shelljs' module to an Angular 2 TypeScript project

I am facing an issue with including the shelljs library in my Angular 2 TypeScript project. I have already added the shelljs.d.ts file to the node_modules/shelljs directory. Below is my package.json configuration: "name": "myproj1", "description": "myp ...

Encountering an error of TypeError while attempting to generate a new GraphQL

Currently using Apollo-Server/TypeScript with graphql-tool's makeExecutableSchema() to set up schema/directives. Encountering an error while attempting to add a basic GraphQL Directive: TypeError: Class constructor SchemaDirectiveVisitor cannot be in ...

Guide to highlighting input field text using Angular

I've set up an angular page that includes an input field within its template. My goal is to highlight the text in the input field when a specific function is triggered. When I refer to "highlighting the text," I mean (check out the image below) https ...

What is the correct way to write SVG markup within SVG tags in a React and NextJS environment?

I currently have a Svg component set up like this interface SvgIconProps { children: React.ReactNode; strokeWidth?: number; width?: number; height?: number; className?: string; } export const SvgIcon = ({ children, strokeWidth = 1, width = ...

Do you think this is a clever way to circumvent using ENUM for a parameter?

As I continue to explore different coding styles in Typescript and Angular, I recently encountered a method without any comments attached to it. It seems like this method is enforcing that the value passed in must be one of the defined options, but strang ...

Is there a way to incorporate a back button feature in a webview?

Check out this helpful tutorial on how to override URL loading in WebView for Android. I am looking to implement a back button function on my website. How can I add one? Currently, when the back button is pressed, the application exits rather than going t ...

Issue with TypeScript retrieving value from an array

Within my component.ts class, I have defined an interface called Country: export interface Country{ id: String; name: String; checked: false; } const country: Country[] = [ { id: 'India', name: 'India', checked: false}, { ...

Discovering the ASP.NET Core HTTP response header in an Angular application using an HTTP interceptor

I attempted to create a straightforward app version check system by sending the current server version to the client in the HTTP header. If there's a newer version available, it should trigger a notification for the user to reload the application. Ini ...

Steps for setting up a nested route in Angular 2

I am currently working on a project that includes an admin page (check the file structure below). I am trying to set up a child route named 'createuser' for the admin page (localhost:4200/admin/createuser). Despite my attempts, I encountered an e ...

Whenever I attempt to host my Node.js app using the GCP deploy command, it fails to work properly. The error message that appears states: "Module 'express' cannot be found."

My NodeJS application is written in TypeScript and utilizes the Express framework. I'm looking to host it on the GCP cloud using the gcloud app deploy command. First, I compile my TS sources to JavaScript - is this the correct approach? Afterwards, I ...

Steps to resolve the 'form' variable being assigned a value but never used in axios:

I am encountering an issue with a contact form that utilizes React with axios on the frontend and Express with nodemailer on the backend while running locally. The expected outcome is for me to receive an email when I click the "Submit" button. However, up ...

The issue with converting a string into an object in Typescript

I am having trouble converting the JSON response from the websocket server to a TypeScript object. I've been trying to debug it but can't seem to find where the error lies. Can anyone assist me in resolving this issue? Below is the code snippet ...

Discovering Type Definitions in Nuxt.js Project Without Manual Imports in VSCode: A Step-by-Step Guide

Having issues with VSCode not recognizing type definitions automatically in a Nuxt.js project with TypeScript. I'm looking to avoid manually importing types in every file. Here's my setup and the problem I'm facing: Configuration My tsconfi ...

A data type labeled as 'undefined' needs to include a method called '[Symbol.iterator]()' which will then return an iterator

I've been working on converting my reducer from JavaScript to TypeScript, but I keep encountering a strange error that I can't seem to resolve. The issue arises when I attempt to use ellipsis for array deconstruction in the reducer [...state.mess ...

Failed attempt to log in to MySQL database from an Android application

I have developed an Android application that connects to a MySQL database, but I am encountering an issue where the 'result' variable in the alert dialog box within backgroundWorker.java's "onPostExecute" function is returning null. Can anyo ...

Ensure that a particular key type is determined by the value of another key within the object (Utilizing Discriminated Unions)

The title of my question may not have been clear about what I am looking for, but what I need is something known as discriminated unions. You can find more information about it here: https://www.typescriptlang.org/docs/handbook/unions-and-intersections.htm ...

Tips for avoiding the push method from replacing my items within an array?

Currently, I am diving into Typescript and VueJS, where I encountered an issue with pushing elements to my array. It seems to constantly override the 'name' property. Let me share the code snippet causing this problem: const itemsSelectedOptions ...