callstack / react-native-paper

Material Design for React Native (Android & iOS)
https://reactnativepaper.com
MIT License
12.96k stars 2.1k forks source link

Paper's button seems to be slower #2821

Closed Elabar closed 2 years ago

Elabar commented 3 years ago

Current behaviour

The button seems to be not as responsive as expected. It just feels laggy. The onPress function seems to be fired after the animation is finished? Please take a look at the gif below where compare the Paper's button with Element's button. The logic in the onPress is exactly the same code.

This only occur on mid/low end device. FYI, my device is running on SD 636.

Expected behaviour

Button should be responsive.

Code sample

https://snack.expo.io/@elabar/paper-button-slow

Screenshots (if applicable)

Highlight:

Highlight:

What have you tried

The problem was found in one of my production apps first. I tried creating a reproduce with a clean npx react-native init, and I can confirm this is a valid issue. The gif above is run on development mode on purpose to show the sluggishness easily.

Strange thing is, this problem is more severe with RN CLI. It feels much better with expo.

I then check on react-native-elements codebase. The main difference I found is Paper is using requestAnimationFrame. Not sure if this is related tho.

Your Environment

software version
ios or android Android 11
react-native 0.64.2
react-native-paper 4.9.2
node 14.16.1
yarn 1.22.10
expo 42.0.1
react-native-vector-icons 8.1.0
github-actions[bot] commented 3 years ago

Couldn't find version numbers for the following packages in the issue:

Can you update the issue to include version numbers for those packages? The version numbers must match the format 1.2.3.

github-actions[bot] commented 3 years ago

Couldn't find version numbers for the following packages in the issue:

Can you update the issue to include version numbers for those packages? The version numbers must match the format 1.2.3.

github-actions[bot] commented 3 years ago

The versions mentioned in the issue for the following packages differ from the latest versions on npm:

Can you verify that the issue still exists after upgrading to the latest versions of these packages?

github-actions[bot] commented 3 years ago

The versions mentioned in the issue for the following packages differ from the latest versions on npm:

Can you verify that the issue still exists after upgrading to the latest versions of these packages?

Ctrl-Mota commented 2 years ago

I have same problem

JerryBels commented 2 years ago

I have a similar issue as well

SignSpice commented 2 years ago

Same problem here. Will check to see if it is an easy fix to mod. Otherwise, I probably just build my own.

edugolive commented 2 years ago

I also made an app using Paper components, and the app was extremely slow

raajnadar commented 2 years ago

It seems the remote debug Js option is enabled. Try disabling it, the issue should not be visible.

Elabar commented 2 years ago

The demo above is run with debug JS enabled on purpose to show the sluggishness more obvious. It is relatively slow when compares to other UI library (RN-Element) even with release build.

You need a device that's running SD 636 and below to spot this performance diff.

raajnadar commented 2 years ago

So it is safe to close the issue because this is not due to react native paper but an issue from react native side.

P.S. you can read this blog post, https://dev.to/paddy57/why-app-gets-slow-in-debug-mode-react-native-191d

Flipper is one of the best option for debugging for react native apps.

Elabar commented 2 years ago

I think I have made my point clear that debug mode is enabled to show the sluggish in a more obvious way. And the sluggish is also noticable in release build.

I tried to poke around the source code and yet can't find the root cause of this performance hit.

But yeah, I think you can close this issue if this kind of performance looks fine to you since I have stopped using any kind of UI libs these days.

Ctrl-Mota commented 2 years ago

The problem persists in release build,

raajnadar commented 2 years ago

I never found any issue on release build try using hermes and other release build optimization techniques.

https://reactnative.dev/docs/performance

Elabar commented 2 years ago

Like I said, you need a device that's running mid to low end processor. But it's fine if you believe the performance is fine.

Collaborator thinks the performance is fine, closing issue.

fgagneten commented 2 years ago

I think we should reopen this issue. Same issue happens on Galaxy J5 (2016) (SM-J510MN) Android's version 7.1.1.

When using the app on debug mode, it is extremly slow. Enabling hermes on release mode works much more better (but still having some delay issues)

raajnadar commented 2 years ago

If you keep the debugger on it will be slow, the below link applies to all the react-native libraries

https://reactnavigation.org/docs/troubleshooting/#app-is-not-working-properly-when-connected-to-chrome-debugger

2nd on low memory you will still find lags maybe the new architecture solves that issue, did you try the new architecture of react-native?

So keeping open makes no sense as the issue is not in the library it is from RN core or its design.

Elabar commented 2 years ago

Just realized my previous replies are not correct.

The demo shown here is not in JS Debug mode. It is just regular development mode.

But yeah, swapping out rn-paper to my custom made components did fix the issue entirely with 60 FPS spinner without delay. Since I was not able to find out root cause of this issue in the library, I will let this issue remains as closed unless otherwise.

raajnadar commented 2 years ago

Can you share a git repo? I will try to run on my end, also mention the steps and the device you used emulator or simulator

Why git repo? snack adds some config itself but with git, I can also see the RN config & I need to see the version of the package which is very important

Elabar commented 2 years ago

ermmmm You can just copy the content in the snack's App.js and pick the required dependencies in package.json.

import React, {useRef} from 'react';
import {View, TextInput, Text, Pressable, ScrollView} from 'react-native';
import {Button as PaperButton} from 'react-native-paper';
import {Formik, useField} from 'formik';
import * as yup from 'yup';
import AsyncStorage from '@react-native-async-storage/async-storage';

const FormikField = ({name, label}) => {
  const [field, meta] = useField(name);

  return (
    <View>
      <Text>{label}</Text>
      <TextInput
        value={field.value}
        onChangeText={field.onChange(name)}
        onBlur={field.onBlur(name)}
        style={{
          color: 'black',
          backgroundColor: '#D1D5DB',
          marginBottom: 10,
          paddingVertical: 4,
        }}
      />
      {meta.touched && meta.error && <Text>{meta.error}</Text>}
    </View>
  );
};

const schema = yup.object().shape({
  username: yup.string().required(),
  password: yup.string().required(),
});

const App = () => {
  const PaperFormRef = useRef(null);
  const ElementFormRef = useRef(null);
  const fetchData = async () => {
    try {
      const raw = await fetch('https://jsonplaceholder.typicode.com/posts', {
        method: 'POST',
        body: JSON.stringify({
          title: 'abc',
          body: 'bar',
          userId: 1,
        }),
        headers: {
          'Content-type': 'application/json; charset=UTF-8',
        },
      });
      const json = await raw.json();
      await AsyncStorage.setItem('post1', JSON.stringify(json));
      await AsyncStorage.setItem('post2', JSON.stringify(json));
      await AsyncStorage.setItem('post3', JSON.stringify(json));
    } catch (err) {
      console.log(err);
    }
  };

  const onSubmit = async () => {
    try {
      await fetchData();
    } catch (err) {
      console.log(err);
    }
  };

  const resetForm = () => {
    PaperFormRef.current.resetForm();
    ElementFormRef.current.resetForm();
  };

  return (
    <View
      style={{
        flex: 1,
        backgroundColor: 'white',
        justifyContent: 'center',
      }}>
      <ScrollView>
        <Pressable
          onPress={resetForm}
          style={{
            marginVertical: 20,
            backgroundColor: 'cyan',
            padding: 10,
            borderRadius: 14,
          }}>
          <Text>Reset forms state</Text>
        </Pressable>
        <Formik
          initialValues={{username: '', password: ''}}
          innerRef={PaperFormRef}
          onSubmit={onSubmit}
          validationSchema={schema}>
          {({submitForm, isSubmitting}) => {
            return (
              <View>
                <Text>Paper Form</Text>
                <FormikField label="Username" name="username" />
                <FormikField label="Password" name="password" />
                <PaperButton
                  mode="contained"
                  onPress={submitForm}
                  style={{marginBottom: 20}}
                  loading={isSubmitting}
                  disabled={isSubmitting}>
                  Paper Button
                </PaperButton>
              </View>
            );
          }}
        </Formik>
      </ScrollView>
    </View>
  );
};

export default App;

For your convenience if you are still interested.

npm install yup formik react-native-paper react-native-safe-area-context @react-native-async-storage/async-storage react-native-vector-icons

or

yarn add yup formik react-native-paper react-native-safe-area-context @react-native-async-storage/async-storage react-native-vector-icons

Note: I omitted the rn-elements in the install command.

fgagneten commented 2 years ago

I said the application is in debug mode (to make the difference between debug/release). When you run an application for every-day development, you run on debug mode. It does not mean I was using the debugger (Chrome Debugger). I just run the code with npx react-native run-android, nothing else and I face the same issue that @Elabar reported

raajnadar commented 2 years ago

@fgagneten can you send a GitHub repo? I will check on my device

fgagneten commented 2 years ago

@raajnadar You can just use the demo from @Elabar here: https://github.com/callstack/react-native-paper/issues/2821#issuecomment-1179242765

raajnadar commented 2 years ago

I am not able to reproducible in the snack that is why I asked for a repro maybe it is because the snack is bumping the SDK version to 45, So I suspect the version is old and the bug was in the old version.

A git repo will be helpful to check the version and config, and this is a very old topic a lot of things improved both in React native paper & expo

Edit: 3 new SDK in expo & 5 new versions in react native, so it is suggested to test with the latest version or provide a runnable git repo to confirm.

fgagneten commented 2 years ago

@raajnadar Uploaded a repo in which I can reproduce with my Galaxy J5 (2016) (SM-J510MN) Android's version 7.1.1.

You can checkout from here: https://github.com/fgagneten/react-native-paper-performance-test

fgagneten commented 2 years ago

@raajnadar You can get rid of react-native-paper on that project and the button should work smoothly again

fgagneten commented 2 years ago

@raajnadar This is the config.ini for an emulator that replicates the device as much as possible:

AvdId=API25
PlayStore.enabled=false
abi.type=armeabi-v7a
avd.ini.displayname=API25
avd.ini.encoding=UTF-8
disk.dataPartition.size=6799M
fastboot.chosenSnapshotFile=
fastboot.forceChosenSnapshotBoot=no
fastboot.forceColdBoot=no
fastboot.forceFastBoot=yes
hw.accelerometer=yes
hw.arc=false
hw.audioInput=yes
hw.battery=yes
hw.camera.back=virtualscene
hw.camera.front=emulated
hw.cpu.arch=arm
hw.cpu.model=cortex-a8
hw.cpu.ncore=2
hw.dPad=no
hw.device.hash2=MD5:d37b758e1a2b070e348378c2efde849a
hw.device.manufacturer=Generic
hw.device.name=4.65in 720p (Galaxy Nexus)
hw.gps=yes
hw.gpu.enabled=yes
hw.gpu.mode=auto
hw.initialOrientation=Portrait
hw.keyboard=yes
hw.lcd.density=320
hw.lcd.height=1280
hw.lcd.width=720
hw.mainKeys=no
hw.ramSize=1024
hw.sdCard=yes
hw.sensors.orientation=yes
hw.sensors.proximity=yes
hw.trackBall=no
image.sysdir.1=system-images/android-25/google_apis/armeabi-v7a/
runtime.network.latency=none
runtime.network.speed=full
sdcard.path=/Users/my-user/.android/avd/API25.avd/sdcard.img
sdcard.size=512 MB
showDeviceFrame=no
skin.dynamic=yes
skin.name=720x1280
skin.path=_no_skin
skin.path.backup=_no_skin
tag.display=Google APIs
tag.id=google_apis
vm.heapSize=80
fgagneten commented 2 years ago

@lukewalczak @Trancever Is there any update on that? Using the new arch works better but still having issues. It is terrible slow on old devices.

bazter commented 1 year ago

I'm glad I'm not alone as I noticed performance issues caused by RNP components but there's no discussion about it anywhere. Even very simple ScrollView became laggy (micro stuttering) after I added RNP buttons to it. Once I replaced RNP buttons in my cards with my own button components (basic touchable views), the stutter was gone and the scroll became buttersmooth again. The stutter definitely wasn't caused by bad optimization as I debugged everything and there were no re-renders happening).

fgagneten commented 1 year ago

On my end, the app entirely depends on RNP. It is sad to see that there is no discussion regarding this issue and the performance when you use and when you don't use RNP is huge. I was able to repro with a really small app with only two screens and I put here the example but seems like there is nothing we can do so far

lukewalczak commented 1 year ago

Hello @fgagneten and @bazter, I was wondering if you have made an initial analysis of the cause of the Paper's button slowness? Additionally, I wanted to inquire if the issue is exclusive to Android devices and if you could provide more information regarding the affected device. Thank you.

bazter commented 1 year ago

Hello @fgagneten and @bazter, I was wondering if you have made an initial analysis of the cause of the Paper's button slowness? Additionally, I wanted to inquire if the issue is exclusive to Android devices and if you could provide more information regarding the affected device. Thank you.

For me the problem was noticable in two different projects (one bare RN, one managed expo) on iOS (both simulator and real device). I didn't dig that deep yet, I just tried to find the cause and removing the paper components from the view made the stutter stop. I'm about to do a little flipper session where I'd like to check if fps is actually dropping or not, but I didn't have time for that yet. I will post an update here once I get to it.

Since there's nothing re-rendering I was thinking that maybe it's just some kind of interferance with animated lib underhood? Hard to say really, I'll let you know if I find anything.

fgagneten commented 1 year ago

@raajnadar Uploaded a repo in which I can reproduce with my Galaxy J5 (2016) (SM-J510MN) Android's version 7.1.1.

You can checkout from here: https://github.com/fgagneten/react-native-paper-performance-test

@lukewalczak Here I left a time ago a reproduce scenario and also put a emulator setting to test it on Android:

https://github.com/callstack/react-native-paper/issues/2821#issuecomment-1186283945

It is extremely slow using Paper, sounds like the issue comes from the animations

I moved on that project example to react-native-elements or just react-native and it is a huge difference performance

fgagneten commented 1 year ago

@raajnadar Could you please re-open this issue again? TIA

lukewalczak commented 1 year ago

To clarify, whether the problem being discussed can be replicated or reproduced on the most recent version of the library?

raajnadar commented 1 year ago

This must be tested on the latest React Native Paper version as well as the latest React Native version to confirm the issue with Hermes turned on