margelo / react-native-graph

📈 Beautiful, high-performance Graphs and Charts for React Native built with Skia

Home Page:https://margelo.io

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Q: How to render current point data correctly?

DDushkin opened this issue · comments

Initially, the UI on gestures works pretty well.

without setState

But if I try to render the current point price and timestamp I get a laggy thing. Here is an example of code with setState:

    const onPointSelected = useCallback(
        (p) => {
            console.log(p);

            const selectedPrice = formatAmount(p.value, fiatCurrency.code as CurrencyName, "fiat");
            const timestamp = DateTime.fromSeconds(p.date);

            setAmountTitle(selectedPrice);
            setTimestamp(timestamp);
        },
        [fiatCurrency.code],
    );

As a result with setState I get slow UI:

with setState

So the question is how to render it properly and smoothly?

Yeah, that's because of React Native. It isn't really fast at state updates. Maybe this will improve with concurrent mode. The way to solve this is to use Reanimated Shared Values and update the Text using ReanimatedText.

@DDushkin : Have you tested the enablePanGesture on a physical device on android?
Not working.

Yeah, that's because of React Native. It isn't really fast at state updates. Maybe this will improve with concurrent mode. The way to solve this is to use Reanimated Shared Values and update the Text using ReanimatedText.

Thanks, I installed AnimateableText from "react-native-animateable-text", and here is the new code

    const title = useSharedValue(assetBalanceFormatted);
    const subtitle = useSharedValue(`${t("main.value")}: ${fiatBalanceFormatted}`);

    const animatedTitle = useAnimatedProps(() => ({
        text: title.value,
    }));
    const animatedSubtitle = useAnimatedProps(() => ({
        text: subtitle.value,
    }));

    const onPointSelected = useCallback(
        (p) => {
            console.log(p);

            const selectedPrice = formatAmount(p.value, fiatCurrency.code as CurrencyName, "fiat");
            const timestamp = DateTime.fromSeconds(p.date);

            title.value = selectedPrice;
            subtitle.value = timestamp.toFormat("d MMM yyyy HH:mm");
        },
        [fiatCurrency.code, subtitle, title],
    );
//...
    <AnimateableText animatedProps={animatedTitle} style={styles.title} />
    <AnimateableText animatedProps={animatedSubtitle} style={styles.subtitle} />

UPD: works now

But I can see now that Cursor is not rendered

Запись экрана 2022-05-06 в 15 50 43

@DDushkin : Have you tested the enablePanGesture on a physical device on android? Not working.

Haven't tried on the device yet

@DDushkin : How did you manage to put that control line you see in the first picture?

@DDushkin : How did you manage to put that control line you see in the first picture?

Added it manually in a fork

@DDushkin : How did you manage to put that control line you see in the first picture?

Added it manually in a fork

It would be great if you could do a pr.

I also needed to display a formatted timestamp without using react-native-animateable-text. I tried using reanimated's shared value, but ran into difficulties formatting the timestamp within the worklet function since I couldn't call methods of Date or other libraries like dayjs. To work around this, I used react-native's TextInput and updated the text using setNativeProps, which seems to be working seamlessly.

So the corresponding props of LineGraph would be like this

onGestureStart={() => {
	gestureStarted.current = true;
}}
onPointSelected={(point) => {
	if (!gestureStarted.current) {
		return;
	}

	selectedPriceRef.current?.setNativeProps({
		text: `${point.value}, ${dayjs(point.date).format('DD MMM')}`,
	});
}}
onGestureEnd={() => {
	gestureStarted.current = false;
	selectedPriceRef.current?.setNativeProps({ text: '' });
}}

The refs are defined as

const selectedPriceRef = useRef<TextInput>(null);
const gestureStarted = useRef(false);

And the TextInput would be like this

<TextInput
  underlineColorAndroid="transparent"
  editable={false}
  ref={selectedPriceRef}
/>