jasongaare / react-native-walkthrough-tooltip

An inline wrapper for calling out React Native components via tooltip
MIT License
610 stars 182 forks source link

Cannot place <Tooltip> inside of a <Text> element #147

Closed apfritts closed 2 years ago

apfritts commented 2 years ago

Just spent my morning wasted on this lovely little gem so I figured I'd just let everyone else know what I found!

Use case

We have a string of text and we want our user's to tap on a word in the middle of the string. We don't want to highlight the entire text block (which can be large), and only want them to tap on a single word.

Problem

If you use the <Tooltip> in the middle of the string of text, it will crash on iOS (and maybe Android?).

Example that causes crash

import React from 'react'
import {StyleSheet, Text, View} from 'react-native'
import Tooltip from 'react-native-walkthrough-tooltip'

const MyScreen: React.FunctionComponent = () => {
  const tapText = () => console.log('tap')
  return (
    <View style={styles.screen}>
      <Text style={styles.textContainer}>
        <Text>You can tap </Text>
        {/* PROBLEM IS Tooltip IS A CHILD OF Text */}
        <Tooltip content={<Text>Tap this</Text>} isVisible={true}>
          <Text onPress={tapText}>here</Text>
        </Tooltip>
        <Text> to edit this text.</Text>
      </Text>
    </View>
  )
}

const styles = StyleSheet.create({
  screen: {flex: 1},
  textContainer: {
    textAlign: 'center',
  },
})

Causes a crash like this:

2022-04-06 12:36:10.633075-0700 mytextapp[1106:54388] *** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: 'Application tried to present modally a view controller <RCTModalHostViewController: 0x10891dd30> that is already being presented by <UIViewController: 0x108933040>.'

My solution

Instead, change the <View> style so that it lays out the text like the <Text> component would (automatically wrapping the text) and remove the <Text> around the tooltip.

import React from 'react'
import {StyleSheet, Text, View} from 'react-native'
import Tooltip from 'react-native-walkthrough-tooltip'

const MyScreen: React.FunctionComponent = () => {
  const tapText = () => console.log('tap')
  return (
    <View style={styles.screen}>
      {/* CHANGED THIS FROM Text TO View */}
      <View style={styles.textContainerForWalkthrough}>
        <Text>You can tap </Text>
        <Tooltip content={<Text>Tap this</Text>} isVisible={true}>
          <Text onPress={tapText}>here</Text>
        </Tooltip>
        <Text> to edit this text.</Text>
      {/* CHANGED THIS FROM Text TO View */}
      </View>
    </View>
  )
}

const styles = StyleSheet.create({
  screen: {flex: 1},
  textContainer: {
    textAlign: 'center',       // REMOVED THIS
    justifyContent: 'center',  // ADDED THIS
    flexDirection: 'row',      // ADDED THIS
    flexWrap: 'wrap',          // ADDED  THIS
  },
})