Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Android] List items are rendered outside of parent height and the onPress event aren't triggered #16

Open
FightFarewellFearless opened this issue Jan 11, 2025 · 16 comments

Comments

@FightFarewellFearless
Copy link

List items are rendered outside of parent height and the TouchableOpacity's onPress event aren't triggered

I'm using shadowlist v0.4.22 with react-native-screens v4.4.0 and @react-navigation/stack

Screenshot

Shadowlist bug

Code:

      <View style={[styles.container, {backgroundColor: thumbnailColor}]}>
        <Shadowlist
          data={data.episodeList.map((item, index) => ({ ...item, id: index.toString() }))}
          renderItem={() => (
            <TouchableOpacity style={styles.episodeButton} onPress={() => {
              console.log('onPress')
              props.navigation.navigate('FromUrl', {
                link: stringify('link'),
              })
            }}>
              <Text style={[globalStyles.text, styles.episodeText, { color: complementThumbnailColor }]}>
                {stringify('title')}
              </Text>
            </TouchableOpacity>
          )}
          keyExtractor={item => item.id}
           />
        </View>
@azimgd
Copy link
Owner

azimgd commented Jan 12, 2025

Hey @FightFarewellFearless,

Thanks for testing this out and sharing your report! I tried to reproduce the layout issue with navigation and screens, but I couldn’t get it to break (navigation react-navigation v7, react-native-screens v4.5). Could you provide some reproduction steps or at least share the styles you're using? It’s likely the problem is with layout calculations or adjustments which I'm willing to fix.

Screenshot 2025-01-12 at 13 04 06 Screenshot 2025-01-12 at 13 04 06

@azimgd
Copy link
Owner

azimgd commented Jan 12, 2025

However, I was able to reproduce the bug where the onPress event isn't triggered. It happens when you click on any appended or prepended elements after scrolling in my case. They seem to lose their InstanceHandle reference, which prevents the events from being dispatched. I’ll look into potential solutions for this.

@FightFarewellFearless
Copy link
Author

FightFarewellFearless commented Jan 12, 2025

Im not sure what is causing the layout issue, im testing on react-native 0.76.5, and even with simple flex: 1 style, it breaks in my case, i'll try to reproduce this in a minimal template. And for the onPress issue, in my case it's not getting triggered every time, even with a very basic Touchable component

@FightFarewellFearless
Copy link
Author

Btw, what react-native version are you using?

@azimgd
Copy link
Owner

azimgd commented Jan 12, 2025

And for the onPress issue, in my case it's not getting triggered every time, even with a very basic Touchable component

Yes, I was able to reproduce this in the latest version.

"react-native": "0.76.5"

@FightFarewellFearless
Copy link
Author

FightFarewellFearless commented Jan 12, 2025

I've tried the latest version u just published, and the issue is still there, even with the example code:

Code in the example folder

import { useRef, useCallback, useEffect } from 'react';
import { View, StyleSheet, Text, Pressable } from 'react-native';
import type { DirectEventHandler } from 'react-native/Libraries/Types/CodegenTypes';
import {
  Shadowlist,
  type OnStartReached,
  type OnEndReached,
  type OnVisibleChange,
  type OnScroll,
  type ShadowlistProps,
  type SLContainerRef,
} from 'shadowlist';

const ITEMS_COUNT = 50;
const IS_INVERTED = false;
const IS_HORIZONTAL = false;
const INITIAL_SCROLL_INDEX = 0;
const FINAL_SCROLL_INDEX = 0;

const ListHeaderComponent = () => (
  <View style={styles.static}>
    <Text style={styles.text}>Header</Text>
  </View>
);

const ListFooterComponent = () => (
  <View style={styles.static}>
    <Text style={styles.text}>Footer</Text>
  </View>
);

const ListEmptyComponent = () => (
  <View style={styles.static}>
    <Text style={styles.text}>Empty</Text>
  </View>
);

export default function App() {
  const data = new Array(ITEMS_COUNT).fill(0).map((_, index) => ({
    id: index.toString(),
  }));
  const ref = useRef<SLContainerRef>(null);

  useEffect(() => {
    if (!FINAL_SCROLL_INDEX) return;
    setTimeout(() => {
      ref.current?.scrollToIndex({ index: FINAL_SCROLL_INDEX });
    }, 1000);
  }, []);

  const onVisibleChange = useCallback<DirectEventHandler<OnVisibleChange>>(
    (event) => {
      event.nativeEvent.visibleEndIndex;
    },
    []
  );

  const onScroll = useCallback<DirectEventHandler<OnScroll>>((event) => {
    event.nativeEvent.contentOffset.y;
  }, []);

  const renderItem: ShadowlistProps['renderItem'] = () => {
    return (
      <Pressable onPress={() => { console.log('onPress') }}>
        <Text  style={styles.text}>{`{{id}}`}</Text>
      </Pressable>
  );
  };

  return (
    <View style={styles.container}>
      <Shadowlist
        ref={ref}
        renderItem={renderItem}
        data={data}
        keyExtractor={(item) => item.id}
        onVisibleChange={onVisibleChange}
        onScroll={onScroll}
        ListHeaderComponent={ListHeaderComponent}
        ListHeaderComponentStyle={styles.static}
        ListFooterComponent={ListFooterComponent}
        ListFooterComponentStyle={styles.static}
        ListEmptyComponent={ListEmptyComponent}
        ListEmptyComponentStyle={styles.static}
        inverted={IS_INVERTED}
        horizontal={IS_HORIZONTAL}
        initialScrollIndex={INITIAL_SCROLL_INDEX}
        numColumns={1}
      />
    </View>
  );
}

const styles = StyleSheet.create({
  container: {
    flex: 1,
    backgroundColor: '#333333',
    paddingTop: 60,
  },
  text: {
    color: '#333333',
    backgroundColor: '#1dd1a1',
    padding: 16,
  },
  static: {
    height: 120,
    backgroundColor: '#576574',
  },
});

I still have the onPress problem and i think the layout issue too, i think some of my dependencies are conflicting with shadowlist? not sure. I'll try with clean project

@azimgd
Copy link
Owner

azimgd commented Jan 12, 2025

Thanks for the update, this is what I get on my end which seems to layout fine?

Android example Screenshot 2025-01-12 at 14 38 21

@FightFarewellFearless
Copy link
Author

FightFarewellFearless commented Jan 12, 2025

Thanks for the update, this is what I get on my end which seems to layout fine?

try changing the height of the container

@azimgd
Copy link
Owner

azimgd commented Jan 12, 2025

I see it now, thanks!

@FightFarewellFearless
Copy link
Author

import { useRef, useCallback, useEffect } from 'react';
import { View, StyleSheet, Text, Pressable } from 'react-native';
import type { DirectEventHandler } from 'react-native/Libraries/Types/CodegenTypes';
import {
  Shadowlist,
  type OnStartReached,
  type OnEndReached,
  type OnVisibleChange,
  type OnScroll,
  type ShadowlistProps,
  type SLContainerRef,
} from 'shadowlist';

const ITEMS_COUNT = 50;
const IS_INVERTED = false;
const IS_HORIZONTAL = false;
const INITIAL_SCROLL_INDEX = 0;
const FINAL_SCROLL_INDEX = 0;

const ListHeaderComponent = () => (
  <View style={styles.static}>
    <Text style={styles.text}>Header</Text>
  </View>
);

const ListFooterComponent = () => (
  <View style={styles.static}>
    <Text style={styles.text}>Footer</Text>
  </View>
);

const ListEmptyComponent = () => (
  <View style={styles.static}>
    <Text style={styles.text}>Empty</Text>
  </View>
);

export default function App() {
  const data = new Array(ITEMS_COUNT).fill(0).map((_, index) => ({
    id: index.toString(),
  }));
  const ref = useRef<SLContainerRef>(null);

  useEffect(() => {
    if (!FINAL_SCROLL_INDEX) return;
    setTimeout(() => {
      ref.current?.scrollToIndex({ index: FINAL_SCROLL_INDEX });
    }, 1000);
  }, []);

  const onVisibleChange = useCallback<DirectEventHandler<OnVisibleChange>>(
    (event) => {
      event.nativeEvent.visibleEndIndex;
    },
    []
  );

  const onScroll = useCallback<DirectEventHandler<OnScroll>>((event) => {
    event.nativeEvent.contentOffset.y;
  }, []);

  const renderItem: ShadowlistProps['renderItem'] = () => {
    return (
      <Pressable onPress={() => { console.log('onPress') }}>
        <Text  style={styles.text}>{`{{id}}`}</Text>
      </Pressable>
  );
  };

  return (
    <View style={styles.container}>
      <Shadowlist
        ref={ref}
        renderItem={renderItem}
        data={data}
        keyExtractor={(item) => item.id}
        onVisibleChange={onVisibleChange}
        onScroll={onScroll}
        ListHeaderComponent={ListHeaderComponent}
        ListHeaderComponentStyle={styles.static}
        ListFooterComponent={ListFooterComponent}
        ListFooterComponentStyle={styles.static}
        ListEmptyComponent={ListEmptyComponent}
        ListEmptyComponentStyle={styles.static}
        inverted={IS_INVERTED}
        horizontal={IS_HORIZONTAL}
        initialScrollIndex={INITIAL_SCROLL_INDEX}
        numColumns={1}
      />
    </View>
  );
}

const styles = StyleSheet.create({
  container: {
    height: 120,
    backgroundColor: '#333333',
    paddingTop: 60,
    borderWidth: 8,
    borderColor: 'red',
  },
  text: {
    color: '#333333',
    backgroundColor: '#1dd1a1',
    padding: 16,
  },
  static: {
    height: 120,
    backgroundColor: '#576574',
  },
});

@FightFarewellFearless
Copy link
Author

Screenshot_20250112_164417_AniFlix
Here's what i got

@FightFarewellFearless
Copy link
Author

Trying to overscroll the list seems to "fix" the layout temporarily

Screenshot_20250112_164517_AniFlix

@FightFarewellFearless
Copy link
Author

I see it now, thanks!

Do you still need a minimal repro template?

@FightFarewellFearless
Copy link
Author

I'll create one if you want

@azimgd
Copy link
Owner

azimgd commented Jan 12, 2025

Nope, thank you @FightFarewellFearless. I'll let you know once fixed.

@FightFarewellFearless
Copy link
Author

Thank you very much @azimgd

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants