Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Slow navigate to a screen contains 12k words (including table) #652

Open
9 of 15 tasks
QuangBinhDinh opened this issue Jan 12, 2024 · 1 comment
Open
9 of 15 tasks
Labels
bug Crush'em all.

Comments

@QuangBinhDinh
Copy link

Decision Table

  • My issue does not look like “The HTML attribute 'xxx' is ignored” (unless we claim support for it)
  • My issue does not look like “The HTML element <yyy> is not rendered”

Good Faith Declaration

Description

I have a very long policy text which contains over 12k words (around 78k chars) on my website and I want to render it on the mobile app. When I try to navigate to the screen contains it, it took 5-6 seconds delay to navigate (video below)

Simulator.Screen.Recording.-.iPhone.14.Pro.-.2024-01-12.at.16.18.19.mp4

Note that I also use @native-html/table-plugin to render table, but even without using it, the navigation is still laggy

Here is my implement code

import React, { memo } from 'react';
import { lightColor } from '@styles/color';
import { SCREEN_WIDTH } from '@util/index';
import RenderHTML, { RenderersProps, MixedStyleRecord, MixedStyleDeclaration } from 'react-native-render-html';
import { normalize } from '@rneui/themed';
import { useNavigateFromWebLink } from '@util/renderHTML';
import WebView from 'react-native-webview';
import TableRenderer, { cssRulesFromSpecs, defaultTableStylesSpecs, tableModel } from '@native-html/table-plugin';
import { base64Font } from '@util/base64';

const baseStyle: MixedStyleDeclaration = {
    fontFamily: 'Poppins-Regular',
    color: '#444444',
    fontSize: normalize(14),
};

const tagsStyles: MixedStyleRecord = {
    b: { fontFamily: 'Poppins-SemiBold', fontWeight: '500' },
    strong: { fontFamily: 'Poppins-Medium', fontWeight: '500' },
    a: { color: lightColor.secondary },
};

const cssRules =
    cssRulesFromSpecs({
        ...defaultTableStylesSpecs,
        linkColor: lightColor.secondary,
        fontFamily: 'Poppins-Regular',
        trOddBackground: 'white',
        fontSizePx: 14,
    }) +
    `
td {
  text-align: left;
  padding: 10px
}
table {
    width: ${SCREEN_WIDTH - 36}px !important;
    height: auto !important;
    border: 1px solid #ccc;
}
@font-face {
    font-family: 'Poppins-Regular';
    font-style: normal;
    font-weight: 500;
    src: url(data:font/ttf;base64,${base64Font});
}
`;
interface IProps {
    html: string;
    showTable?: boolean;
}

const RenderPrintervalHtml = ({ html, showTable }: IProps) => {
    const { navigateFromLink } = useNavigateFromWebLink();
    const renderersProps: Partial<RenderersProps> = {
        img: { enableExperimentalPercentWidth: true },
        a: {
            onPress: async (_, href) => {
                //console.log('Link clicked', href);
                navigateFromLink(href);
            },
        },
        table: {
            cssRules,
            computeContainerHeight() {
                return null;
            },
        },
    };

    const newHtml = showTable
        ? html.replace(/<table.+?>/, `<table border="1">`)
        : html.replace(/<table\b[^>]*>[\s\S]*?<\/table>/g, '');

    return (
        <RenderHTML
            {...(showTable && {
                customHTMLElementModels: { table: tableModel },
                WebView,
                renderers: { table: TableRenderer },
            })}
            contentWidth={SCREEN_WIDTH}
            renderersProps={renderersProps}
            baseStyle={baseStyle}
            tagsStyles={tagsStyles}
            enableExperimentalMarginCollapsing
            source={{ html: newHtml }}
            systemFonts={['Poppins-Regular', 'Poppins-Medium', 'Poppins-Bold', 'Poppins-SemiBold']}
        />
    );
};

export default memo(RenderPrintervalHtml);

Any solution to deal with this scenario would be appreciated !

React Native Information

react-native version: 0.72.4

RNRH Version

react-native-render-html version: 6.3.4
@native-html/table-plugin version : 5.3.1

Tested Platforms

  • Android
  • iOS
  • Web
  • MacOS
  • Windows

Reproduction Platforms

  • Android
  • iOS
  • Web
  • MacOS
  • Windows

Minimal, Reproducible Example

I try to create an exact version of this scenario but seem I can't (Snack install @react-navigation/native failed) . Also my RenderHTML is using custom fonts and base64 font (you can see in the code) so I don't know how to do it with Snack. But I already created a simple version of this, you can check it here: https://snack.expo.dev/@quangbinh1999/rnrhtml-template. The "very long html" is fetched from my server and you can find it in html variable. I hope this does some help.

Additional Notes

No response

@QuangBinhDinh QuangBinhDinh added the bug Crush'em all. label Jan 12, 2024
@SashaGo3
Copy link

Having similar issue, that is more related to react-navigation pre-rendering

I handled it by showing loader.

import { useFocusEffect } from '@react-navigation/native'

export const Screen = () => {
  const [isReady, setIsReady] = React.useState(false)
  
  useFocusEffect(
    useCallback(() => {
      setTimeout(() => setIsReady(true), 1000)

      return () => setIsReady(false)
    }, []),
  )

  if (!isReady) {
    return <Loader />
  }
  
  return <HeavyComponent /> 
  
}

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Crush'em all.
Projects
None yet
Development

No branches or pull requests

2 participants