xcarpentier / rn-tourguide

🚩Make an interactive step by step tour guide for your react-native app (a rewrite of react-native-copilot)
https://xcarpentier.github.io/rn-tourguide/
Other
733 stars 213 forks source link

How to use it for a single child in a ScrollView? #66

Closed robertoosantos closed 1 year ago

robertoosantos commented 3 years ago

May someone share an example about how to use it for a single child in a ScrollView?

I have a ScroolView where the children components are rendered by Array.map function and I'd like to highlight the very first child component with something like 'start here'.

bucketclan commented 2 years ago

You could just wrap the child with the required index with the TourGuideZone

For e.g a fully working example below

import React from 'react';
import {
  StyleSheet,
  View,
  SafeAreaView,
  ScrollView,
  StatusBar,
  Text,
} from 'react-native';
import {
  TourGuideProvider, // Main provider
  TourGuideZone, // Main wrapper of highlight component
  useTourGuideController, // hook to start, etc.
} from 'rn-tourguide';

function App() {
  return (
    <TourGuideProvider androidStatusBarVisible={true} {...{borderRadius: 16}}>
      <AppContent />
    </TourGuideProvider>
  );
}

const AppContent = () => {
  // Use Hooks to control!
  const {
    canStart, // a boolean indicate if you can start tour guide
    start, // a function to start the tourguide
    eventEmitter, // an object for listening some events
  } = useTourGuideController();

  // Can start at mount 🎉
  // you need to wait until everything is registered 😁
  React.useEffect(() => {
    if (canStart) {
      // 👈 test if you can start otherwise nothing will happen
      start();
    }
    // eslint-disable-next-line react-hooks/exhaustive-deps
  }, [canStart]); // 👈 don't miss it!

  const handleOnStart = () => console.log('start');
  const handleOnStop = () => console.log('stop');
  const handleOnStepChange = () => console.log(`stepChange`);

  React.useEffect(() => {
    eventEmitter.on('start', handleOnStart);
    eventEmitter.on('stop', handleOnStop);
    eventEmitter.on('stepChange', handleOnStepChange);

    return () => {
      eventEmitter.off('start', handleOnStart);
      eventEmitter.off('stop', handleOnStop);
      eventEmitter.off('stepChange', handleOnStepChange);
    };
    // eslint-disable-next-line react-hooks/exhaustive-deps
  }, []);
  const testArray = Array.from(Array(10).keys());

  return (
    <SafeAreaView style={styles.container}>
      <ScrollView style={styles.scrollView}>
        {testArray.map(value => {
          if (value === 1) {
            return (
              <TourGuideZone zone={1} text={'Step 1'} borderRadius={16}>
                <Row key={value} value={value} />
              </TourGuideZone>
            );
          }

          if (value === 3) {
            return (
              <TourGuideZone zone={2} text={'Step 3'} borderRadius={16}>
                <Row key={value} value={value} />
              </TourGuideZone>
            );
          }

          return <Row key={value} value={value} />;
        })}
      </ScrollView>
    </SafeAreaView>
  );
};

const Row = ({value}) => {
  return (
    <View
      style={{
        height: 100,
        width: '100%',
        backgroundColor: 'red',
        alignItems: 'center',
        justifyContent: 'center',
        borderBottomWidth: 1,
        borderBottomColor: 'black',
      }}>
      <Text>Value: {value}</Text>
    </View>
  );
};

const styles = StyleSheet.create({
  container: {
    flex: 1,
    paddingTop: StatusBar.currentHeight,
  },
  scrollView: {
    backgroundColor: 'pink',
    marginHorizontal: 20,
  },
  text: {
    fontSize: 42,
  },
});

export default App;