I am creating my first react native app with expo and i am shocked that the app cannot seem to handle a modal with an input field with local state. I am wondering if others have had the same experience or perhaps I am missing something? I have a gluestack modal with 1 input field. The entire page is one file. I can make things smooth by putting the input in its own file and using useImperitiveHandle to capture the input value on form submission, but I was simply shocked that I had to resort to that method with such a simple UI. Am i just being naive to the capabilities of a RN app, or is there a better way to do things? I also tried using a react Native Paper Modal instead of gluestack, but ran into the same issue. When I enter text into the input fields the UI stutters and is choppy. It only occurs when the input field is inside the modal. I have noticed the bad behavior on device and simulator.
Behavior recorded here
import React, { useState } from "react";
import uuid from "react-native-uuid";
import { Button, ButtonIcon, ButtonText } from "@/components/ui/button";
import { Heading } from "@/components/ui/heading";
import {
Modal,
ModalBackdrop,
ModalContent,
ModalCloseButton,
ModalHeader,
ModalBody,
ModalFooter,
} from "@/components/ui/modal";
import { Icon, CloseIcon, AddIcon } from "@/components/ui/icon";
import { Input, InputField } from "@/components/ui/input";
import { View } from "react-native";
import {
TextInput as PaperTextInput,
Modal as PaperModal,
Button as PaperButton,
Portal,
} from "react-native-paper";
export default function PerfTest() {
const [modalVisible, setModalVisible] = useState(false);
const [nameText, setNameText] = useState<string>("");
const [visible, setVisible] = React.useState(false);
const showModal = () => setVisible(true);
const hideModal = () => setVisible(false);
const closeModal = () => {
setModalVisible(false);
setNameText("");
};
const onPressAdd = async () => {
const name = nameText;
const id = uuid.v4();
const newItem = {
id,
name,
};
closeModal();
};
return (
<View>
<Button
style={{ margin: 20 }}
size="lg"
variant="solid"
onPress={() => setModalVisible(true)}
>
<ButtonText>New Item</ButtonText>
<ButtonIcon as={AddIcon} className="ml-2" />
</Button>
<Modal
className="justify-center items-center"
isOpen={modalVisible}
onClose={() => {
setModalVisible(false);
}}
size="full"
>
<ModalBackdrop />
<ModalContent>
<ModalHeader>
<Heading size="md" className="text-typography-950">
New Item
</Heading>
<ModalCloseButton>
<Icon
as={CloseIcon}
size="md"
className="stroke-background-400 group-[:hover]/modal-close-button:stroke-background-700 group-[:active]/modal-close-button:stroke-background-900 group-[:focus-visible]/modal-close-button:stroke-background-900"
/>
</ModalCloseButton>
</ModalHeader>
<ModalBody>
{/**the input lags i think because of rerendering the modal */}
<Input>
<InputField
autoCapitalize="none"
autoComplete="off"
autoCorrect={false}
value={nameText}
onChangeText={setNameText}
placeholder="Name..."
/>
</Input>
<PaperTextInput value={nameText} onChangeText={setNameText} />
{/* LAGS <TextInput LAGS
style={{ borderWidth: 2, marginTop: 10 }}
value={nameText}
onChangeText={setNameText}
></TextInput> */}
</ModalBody>
<ModalFooter>
<Button
variant="outline"
action="secondary"
onPress={() => {
setModalVisible(false);
}}
>
<ButtonText>Cancel</ButtonText>
</Button>
<Button
onPress={() => {
onPressAdd();
}}
>
<ButtonText>Save</ButtonText>
</Button>
</ModalFooter>
</ModalContent>
</Modal>
<Portal>
<PaperModal visible={visible} onDismiss={hideModal}>
<PaperTextInput value={nameText} onChangeText={setNameText} />
</PaperModal>
</Portal>
<Button style={{ marginTop: 30 }} onPress={showModal}>
Show
</Button>
</View>
);
}