Below I have a very simple component. The goal is to make sure that this component does not eat gestures of the parent component (such as pan and zoom). This is why the initial state is a just a View but when the user wants to edit, they will tap on the Input and the logic below should swap the view with the TextInput. However, this component crashes when the tap gesture is detected within this component. I've tried many things. What am I not seeing?
Thank you.
export default function PanableTextInput() {
const [value, setValue] = useState<string>("")
const [editing, setEditing] = useState<boolean>(false)
const tapGesture = Gesture.Tap()
.onEnd(() => {
console.log("Pressed!") // never logs unless line below is commented out
setEditing(true)
})
if (editing) {
return (
<TextInput value={value} onChangeText={(newValue) => setValue(newValue)} />
)
}
return (
<GestureDetector
gesture={tapGesture}
>
<View style={{
flexGrow: 1,
borderBottomWidth: 2,
borderColor: "#d3d3d3",
height: 40
}}>
<Text style={{ flex: 1 }}>
{value}
</Text>
</View>
</GestureDetector>
)
}
This is a thread's issue. onEnd
callback runs on UI thread and setEditing
must run on JS thread, so crash is happening because you try to call JS function from UI thread. To prevent this code from crashing JS code should be scheduled to be evaluated in the corresponding thread. So just change that line with state change to runOnJS(setEditing)(true)