Skip to content

The problem of the new React Native #349

@ArtsiomAstrouski

Description

@ArtsiomAstrouski

Current Behavior
auto scroll doesn't work when switching between blocks - ref.measureLayout must be called with a ref to a native component.

import React, { useRef, useState } from 'react';
import { useTranslation } from 'react-i18next';
import { ScrollView, Text, TouchableOpacity, View, SafeAreaView, RefreshControl } from 'react-native';
import { CopilotProvider, CopilotStep, useCopilot, walkthroughable } from 'react-native-copilot';
import getCopilotLabel from '../../../../src/utils/helpers/getCopilotLabel';
import styles from './styles';

const WalkthroughableTouchableOpacity = walkthroughable(TouchableOpacity);

const mockSettingsData = [
  { id: '1', title: 'Wi-Fi Settings', type: 'setting' },
  { id: '2', title: 'Notification Settings', type: 'setting' },
  { id: '3', title: 'Sound Settings', type: 'setting' },
  { id: '4', title: 'Display Settings', type: 'setting' },
  { id: '5', title: 'Privacy Settings', type: 'setting' },
  { id: '7', title: 'Delete Device', type: 'danger' },
  { id: '8', title: 'Sound Settings', type: 'setting' },
  { id: '9', title: 'Display Settings', type: 'setting' },
  { id: '10', title: 'Privacy Settings', type: 'setting' },
  { id: '11', title: 'Delete Device', type: 'danger' },
  { id: '12', title: 'Sound Settings', type: 'setting' },
  { id: '13', title: 'Sound Settings', type: 'setting' },
  { id: '14', title: 'Display Settings', type: 'setting' },
  { id: '15', title: 'Privacy Settings', type: 'setting' },
  { id: '16', title: 'Delete Device', type: 'danger' },
  { id: '17', title: 'Sound Settings', type: 'setting' },
  { id: '18', title: 'Display Settings', type: 'setting' },
  { id: '19', title: 'Privacy Settings', type: 'setting' },
  { id: '20', title: 'Delete Device', type: 'danger' },
];

const SettingsScreenMock = () => {
  const { start } = useCopilot();
  const scrollViewRef = useRef(null);
  const [refreshing, setRefreshing] = useState(false);

  const onRefresh = () => {
    setRefreshing(true);
    setTimeout(() => setRefreshing(false), 1000);
  };

  const startTutorial = () => {
    start(false, scrollViewRef.current);
  };

  return (
    <SafeAreaView style={{ flex: 1 }}>
      <View style={{ padding: 16 }}>
        <TouchableOpacity onPress={startTutorial} style={{ padding: 10, backgroundColor: '#007AFF', borderRadius: 8, marginBottom: 16 }}>
          <Text style={{ color: 'white', textAlign: 'center' }}>Start Tutorial</Text>
        </TouchableOpacity>
      </View>

      <ScrollView ref={scrollViewRef} style={{ flex: 1 }} refreshControl={<RefreshControl refreshing={refreshing} onRefresh={onRefresh} tintColor='#007AFF' />}>
        {mockSettingsData.map((item, index) => (
          <CopilotStep key={item.id} name={`step-${index}`} order={index} text={`This is step ${index + 1}: ${item.title}`}>
            <WalkthroughableTouchableOpacity
              style={{
                padding: 16,
                borderBottomWidth: 1,
                marginBottom: 50,
                borderBottomColor: '#EEE',
                backgroundColor: item.type === 'danger' ? '#FFF0F0' : 'white',
              }}
            >
              <Text style={{ color: item.type === 'danger' ? '#FF3B30' : '#000' }}>{item.title}</Text>
            </WalkthroughableTouchableOpacity>
          </CopilotStep>
        ))}

        {/* Дополнительные элементы для прокрутки */}
        {Array.from({ length: 10 }).map((_, index) => (
          <View key={`extra-${index}`} style={{ padding: 20, backgroundColor: index % 2 === 0 ? '#F5F5F5' : 'white' }}>
            <Text>Additional item {index + 1}</Text>
          </View>
        ))}
      </ScrollView>
    </SafeAreaView>
  );
};

const SettingsContainer = () => {
  const { t } = useTranslation('guides');
  const labels = getCopilotLabel(t);

  return (
    <CopilotProvider tooltipStyle={styles.copilot} stopOnOutsideClick androidStatusBarVisible labels={labels}>
      <SettingsScreenMock />
    </CopilotProvider>
  );
};

export default SettingsContainer;

Environment

  • Device: [e.g. iPhone 8 Simulator]
  • OS: [e.g. iOS12]
  • react-native-copilot: 3.3.3
    "react-native": "^0.79.6",
    "react-native-svg": "15.12.x",

Possible Solution

It is necessary to change the logic of working with the ref, because it changed when connecting Fabric

Additional context/Screenshots

2025-09-05.23.00.20.mov

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions