react-nativegesturegesture-recognition

Gesture.Tap crashes the app on setting local state


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>
  )
}

Solution

  • 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)