Skip to content

Performance issue when Dispatching Redux Actions from KeyEvent Listener? #88

@fdibQat

Description

@fdibQat

We have an issue when calling a function that does some redux store dispatch and computations, it will take considerably longer when called from the KeyEvent listener, than calling it directly from, for example, a Button onPress.

In the attached code, if I call the saveData function directly from the Button onPress it takes between 6 and 20 milliseconds.
If I call the function from within the KeyEvent, it will take a lot longer. Consistently between 40 and 60+ milliseconds.

I've created a repo to show the issue.
https://github.com/fdibQat/rn-keyevent-perfomance

In this case, using an anonymized repo, with such small times it's not really a problem, but we have some more real-life complex code where a 1-second operation takes 6 or 7 seconds when called from the KeyEvent listener, which is very much noticeable.

import React, { useEffect, useState } from "react"; import { Button, StyleSheet, Text, View } from "react-native"; import KeyEvent from "react-native-keyevent"; import { TestData, TestItem, addItemToTestData } from "./testSlice"; import { useSelector, useDispatch } from "react-redux"; import { RootState } from "./store"; const KeyCatcher = () => { const testData = useSelector((state: RootState) => state.testData); const [keyCode, setKeyCode] = useState("nothing has been pressed yet"); const KEYBOARD_KEYS = { arrowDown: 20, arrowLeft: 21, arrowRight: 22, arrowUp: 19, f1: 131, f2: 132, f3: 133, f4: 134, f5: 135, f6: 136, f7: 137, tab: 61, } as const; type KeyboardKeys = (typeof KEYBOARD_KEYS)[keyof typeof KEYBOARD_KEYS]; const dispatch = useDispatch(); // Heavy operation mock function const heavyOperation = (testData: TestData[], itemToAdd: TestItem) => { const start = performance.now(); const sum = testData.reduce((acc, testDataItem) => { const abcSum = testDataItem.testItems?.reduce( (abcAcc, item) => abcAcc + item.abc, 0 ) || 0; return acc + abcSum; }, 0); const total = sum + itemToAdd.abc; const end = performance.now(); console.log(`Time taken to execute heavy operation is ${end - start}ms.`); return total; }; const saveData = (calledFrom: string) => { console.log(">>> Save data started: <<<"); console.log("Called from:", calledFrom); const start = performance.now(); const itemToAdd = { abc: 1, name: "TEST 3", price: 1, sequence: 1, status: true, updatedAt: new Date().toISOString(), value: 1, volume: 1, xCode: "Y3", xyz: 1, yCode: "Y3", }; const randomHeavyOp = heavyOperation(testData, itemToAdd); console.log("Total randomHeavyOp value:", randomHeavyOp); testData.forEach((testDataItem) => { const similarItem = testDataItem.testItems?.find( (item) => item.name === itemToAdd.name ); if (similarItem) { console.log("Found a similar item with name:", similarItem.name); } else { console.log("No similar item found"); } }); dispatch(addItemToTestData({ testID: "LN123567", testItem: itemToAdd })); console.log(">>> Save data finished <<<"); const end = performance.now(); console.log("Time taken to execute add function is: ", end - start, "ms."); }; useEffect(() => { KeyEvent.onKeyDownListener( (keyEvent: { keyCode: KeyboardKeys; action: string; pressedKey: string; }) => { console.log( "Key pressed:", keyEvent.keyCode, keyEvent.action, keyEvent.pressedKey ); setKeyCode(keyEvent.keyCode.toString()); switch (keyEvent.keyCode) { case KEYBOARD_KEYS.f2: saveData("F2 Key pressed"); break; default: break; } } ); return () => KeyEvent.removeKeyDownListener(); // eslint-disable-next-line react-hooks/exhaustive-deps }, []); return ( <View style={styles.container}> <Text> Key Code pressed: {keyCode} {testData[0].testItems.length} </Text> <Button title="Save this" onPress={() => saveData("Button onPress")} /> </View> ); }; export default KeyCatcher; const styles = StyleSheet.create({ container: { flex: 1, backgroundColor: "#9fb4b6", alignItems: "center", justifyContent: "center", borderWidth: 1, borderColor: "black", }, });

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions