Flatlist in Modal unable to scroll

See original GitHub issue

I’m having an issue with scrolling in lists that are in modals ever since upgrading from 0.46.4 to the latest React-Native version (0.55.4). In this case it is a Flatlist.

The Flatlist with the problem is inside a modal, which is in another modal that is rendered as a footer component on another Flatlist (it is an add button).

Initial page: Flatlist items, footer component: add button Add Button: Modal with input fields. Upon clicking an input field another modal pops up. Input field: Modal with Flatlist

Environment

Environment: OS: Linux 4.13 Node: 8.9.1 Yarn: 1.5.1 npm: 4.6.1 Watchman: Not Found Xcode: N/A Android Studio: Not Found

Packages: (wanted => installed) react: ^16.3.2 => 16.3.2 react-native: ^0.55.4 => 0.55.4

Steps to Reproduce

Add button code (button component is my own):

import { observable } from 'mobx';
import { observer } from 'mobx-react';

@observer
class AddButton extends Component {
    @observable visible = false;

    constructor(props) {
        super(props);
        this.state = {
            mergeName: '',
            coin: undefined
        };
    }
    show = () => {
        this.visible = true;
    };

    hide = () => {
        this.visible = false;
    };

    render() {

        return (
            <View>
                <Button
                    primary
                    onPress={() => {
                        this.show();
                    }}
                    title={'add'}
                    style={{
                        width: '50%',
                        alignSelf: 'center',
                        marginVertical: 16
                    }}
                />
                <Modal
                    visible={this.visible}
                    animationType='slide'
                    onRequestClose={this.hide}
                >
                    <Screen>
                        <View style={{ padding: 5, backgroundColor: '#0003' }}>
                            <TouchableOpacity
                                style={{
                                    width: '50%',
                                    height: 40,
                                    paddingHorizontal: 10,
                                    justifyContent: 'center'
                                }}
                                onPress={this.hide}
                            >
                                <Text style={{ color: '#fff' }}>
                                    {'cancel'}
                                </Text>
                            </TouchableOpacity>
                        </View>

                        <View>
                            <Row>
                                <RowLabel>{'coin'}:</RowLabel>
                                <Selector
                                    force
                                    ref={'mySelector'}
                                    value={this.coin}
                                    onSelect={coin => {
                                        this.handleSelect();
                                    }}
                                    data={allCoins}
                                />
                            </Row>
                            <Button
                                primary
                                onPress={this.handleSubmit}
                                title={this.props.i18n.'add'}
                                style={{
                                    width: '50%',
                                    alignSelf: 'center',
                                    marginVertical: 16
                                }}
                            />
                        </View>
                    </Screen>
                </Modal>
            </View>
        );
    }
}

export default AddButton;

const contentStyle = {
    flex: 1,
    backgroundColor: '#0003',
    paddingLeft: 10,
    borderRadius: 3
};

const Row = ({ style, ...rest }) => (
    <View
        style={[
            {
                height: 60,
                flexDirection: 'row',
                alignItems: 'center',
                padding: 10,
                marginRight: 10
            },
            style
        ]}
        {...rest}
    />
);

const RowLabel = props => (
    <Text style={{ width: 80, color: '#ccc' }} {...props} />
);

const Input = (props: TextInputProperties) => (
    <View style={contentStyle}>
        <TextInput
            placeholderTextColor='#fff3'
            style={{ color: '#ccc', flex: 1, fontSize: 14 }}
            {...props}
        />
    </View>
);

Problematic Flatlist code:

@observer
class Selector extends Component {
    @observable value = '';
    @observable visible = false;
    constructor(props) {
        super(props);
        if (props.modify) {
            this.selectValue();
        }
    }

    selectValue = () => {
        this.value = this.props.value;
    };

    show = () => {
        if (this.props.force) this.visible = true;
        if (!this.props.coin) return;
        this.visible = true;
    };

    hide = () => {
        this.filterText = '';
        this.visible = false;
    };

    handleSelect = item => {
        this.value = item;
        if (typeof this.props.onSelect === 'function') {
            this.props.onSelect(item);
        }
        this.hide();
    };

    componentWillReceiveProps(nextProps) {
        if (nextProps.value !== this.value) {
            this.value = nextProps.value || '';
        }
    }

    renderItem = ({ item }) => {
        return (
            <TouchableOpacity
                onPress={() => this.handleSelect(item)}
                style={{
                    backgroundColor: '#fff',
                    height: 40,
                    paddingLeft: 10,
                    justifyContent: 'center'
                }}
            >
                <Text style={{ fontSize: 14, color: '#333' }}>
                    {item.toUpperCase()}
                </Text>
            </TouchableOpacity>
        );
    };

    render() {
        let data = this.props.data;

        return (
            <View style={[ contentStyle, { justifyContent: 'center' } ]}>
                <TouchableOpacity
                    style={{
                        flex: 1,
                        flexDirection: 'row',
                        alignItems: 'center'
                    }}
                    onPress={this.show}
                >
                    <Text
                        numberOfLines={1}
                        style={{ color: this.value ? '#ccc' : '#fff3' }}
                    >
                        {(
                            this.value ||
                            this.props.placeholder ||
                            ''
                        ).toUpperCase()}
                    </Text>
                </TouchableOpacity>

                <Modal
                    transparent
                    animationType='fade'
                    visible={this.visible}
                    onRequestClose={this.hide}
                >
                    <View
                        style={{
                            flex: 1,
                            backgroundColor: '#0005',
                            alignItems: 'center',
                            paddingTop: 80
                        }}
                    >
                        <View
                            style={{
                                width: '80%',
                                backgroundColor: '#fff',
                                borderRadius: 5,
                                maxHeight: '80%',
                                overflow: 'hidden'
                            }}
                        >
                            <FlatList
                                data={data}
                                keyExtractor={i => i}
                                getItemLayout={(_, index) => {
                                    const height = 40 + HairSpacer.width;
                                    return {
                                        length: height,
                                        offset: height * index,
                                        index
                                    };
                                }}
                                ItemSeparatorComponent={HairSpacer}
                                renderItem={this.renderItem}
                            />
                        </View>
                        <TouchableOpacity
                            onPress={this.hide}
                            style={{ marginTop: 12 }}
                        >
                            <Icon
                                name='ios-close-circle'
                                size={50}
                                color='#ccc'
                            />
                        </TouchableOpacity>
                    </View>
                </Modal>
            </View>
        );
    }
}

export default Selector;

const contentStyle = {
    flex: 1,
    backgroundColor: '#0003',
    paddingLeft: 10,
    borderRadius: 3
};

Expected Behavior

I expect to be able to scroll freely, as in previous versions of react-native

Actual Behavior

Cannot scroll the flatlist. Tried all the suggested options online, including flexgrow, messing around with other styling, onStartShouldSetResponder, etc

Issue Analytics

  • State:closed
  • Created 5 years ago
  • Reactions:2
  • Comments:12

github_iconTop GitHub Comments

4reactions
audiolioncommented, Aug 8, 2018

Having this same issue, @abeddow91 solution worked for me:

<ScrollView>
  <FlatList
    // ...
  />
</ScrollView>

Dont’ forget to move any container styles from the FlatList to the ScrollView

1reaction
abeddow91commented, Aug 8, 2018

I managed to get around this by wrapping the flatlist within a scrollview - not very nice code but its working as expected

Read more comments on GitHub >

github_iconTop Results From Across the Web

React-Native: Flatlist in Modal unable to scroll - Stack Overflow
In order to bound the height of a ScrollView, either set the height of the view directly (discouraged) or make sure all parent...
Read more >
Flatlist not scrolling inside modal, need help fixing it! - Reddit
My Flatlist is not scrolling inside a modal. I have tried adding contentContainerStyle={{ flexGrow: 1 }} but it still doesn't work. I also ......
Read more >
FlatList - React Native
Instead of starting at the top with the first item, start at initialScrollIndex . This disables the "scroll to top" optimization that keeps...
Read more >
Troubleshooting | React Native Bottom Sheet - GitHub Pages
To resolve this issue, please use ScrollView & FlatList from react-native-gesture-handler provide instead react-native . import { ScrollView, FlatList } ...
Read more >
react-native-modal - npm
I can't scroll my ScrollView inside of the modal. Enable propagateSwipe to allow your child components to receive swipe events: <Modal ...
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found