реагировать на родную модальную задержку и рывковую анимацию - PullRequest
0 голосов
/ 09 апреля 2020

Я пытаюсь создать собственный экран реакции с каруселью слева и справа, на каждой панели карусели есть вертикальный плоский список со списком элементов. Максимум - это 8-10 панелей карусели и от 5 до 30 элементов в плоском вертикальном плоском списке, так что, возможно, 300 для большинства отображаемых элементов, но обычно 100.

Я вызываю API и проверяю данные на моем сервер каждые 2-3 секунды и установка состояния в моем компоненте с новыми данными. В настоящее время это работает, и данные данных в дочерних компонентах обновляются, как и должно.

Каждый элемент в плоском списке является интерактивным, что вызывает модальное всплывающее окно, которое запускается на странице. Проблема, которую я имею, состоит в том, что модальное всплывающее окно занимает 4-5 секунд, чтобы появиться и закрыть. Кроме того, когда модал, наконец, начинает исчезать, анимация прерывистая, и темный фоновый слой кажется удаленным sh при его удалении.

Сначала я попробовал встроенный модал и также использовал реакцию -native-модальный пакет и оба одинаковы.

Я пытался использовать InteractionManager.runAfterInteractions, а также shouldComponentUpdate (nextProps, nextState), чтобы попытаться заблокировать мои вызовы API до завершения анимации или остановить мой isModalVisible. Государственная собственность от повторного рендеринга при его изменении.

Код ниже, любая помощь будет оценена.

import {
    Text,
    Button,
    StyleSheet,
    View,   
    FlatList,   
    Dimensions,
    Image,
    Animated,
    SafeAreaView,
    TouchableHighlight,
    InteractionManager,
} from 'react-native';
import React from 'react';
import Title from './Title';
import CarouselMeeting from './CarouselMeeting';
import Modal from 'react-native-modal';
import Carousel from 'react-native-snap-carousel';

class MeetingDisplay extends React.Component {
constructor(props) {
    super(props);        
    this.state = {
        raceList: [],
        meetingList: [],
        meetingId: props.navigation.state.params.meetingId,
        currentIndex: 0,
        raceCount: 0,
        activeIndex: 0,
        isModalVisible: false,
    }
    this.refreshScreen = this.refreshScreen.bind(this)
}

componentDidMount() {
    InteractionManager.runAfterInteractions(() => {
    Promise.all([fetch('http://apicallurl?id' + this.state.meetingId), fetch('http://apicallurl?id' + this.state.meetingId)])
        .then(([res1, res2]) => {
            return Promise.all([res1.json(), res2.json()])
        })
        .then(([res1, res2]) => {
            this.setState({
                raceList: res1,
                meetingList: res2.Meets,

            })
        });
    this.interval = setInterval(() => this.updateRaceList(), 3000);
});
}

componentDidUpdate(prevProps, prevState) {
    InteractionManager.runAfterInteractions(() => {
    if (prevState.meetingId !== this.state.meetingId) {
        Promise.all([fetch('http://apicallurl?id' + this.state.meetingId), fetch('http://apicallurl?id' + this.state.meetingId)])

            .then(([res1, res2]) => {
                return Promise.all([res1.json(), res2.json()])
            })
            .then(([res1, res2]) => {
                this.setState({
                    raceList: res1,
                    meetingList: res2.Meets,

                })
            });
    }
});
}

async updateRaceList() {
    InteractionManager.runAfterInteractions(() => {
        fetch('http://apicallurl' + this.state.meetingId)
            .then((response) => response.json())
            .then((responseJson) => {
                this.setState({
                    raceList: responseJson,
                }, function () {

                });
            })
            .catch((error) => {
                console.error(error);
            });
    });
}

toggleModal = () => {
    InteractionManager.runAfterInteractions(() => {
        this.setState({ isModalVisible: !this.state.isModalVisible });
    });
};

shouldComponentUpdate(nextProps, nextState) {
    if(this.state.isModalVisible !== nextState.isModalVisible){
     this.setState({ isModalVisible: nextState.isModalVisible})
     return false;
    } else return true;
  }

render() {
    const peek = 20;
    const gutter = peek / 4;
    const cardWidth = Dimensions.get('window').width - gutter * 2 - peek * 2;
    const contentOffset = (Dimensions.get('window').width - (cardWidth + (gutter * 2))) / 2;

    return (
        <>
            <Title heading={this.state.raceList.VenueName} />                

            <SafeAreaView style={{ flex: 1, backgroundColor: 'rebeccapurple', paddingTop: 50, }}>
                <View style={{ flex: 1, flexDirection: 'row', justifyContent: 'center', }}>
                    <Carousel
                        layout={"default"}
                        useScrollView
                        ref={ref => this.Carousel = ref}
                        data={this.state.raceList.RaceList}
                        sliderWidth={cardWidth}
                        itemWidth={cardWidth - gutter * 2 - peek * 2}
                        onSnapToItem={index => this.setState({ activeIndex: index })}
                        renderItem={({ item }) => (
                            <Animated.View style={{
                                flex: 1,
                                paddingTop: 20,
                                width: cardWidth,                                    
                                margin: gutter,
                                backgroundColor: 'blue',
                                justifyContent: 'center',
                                alignItems: 'center',
                            }}>
                                <FlatList
                                    horizontal={false}
                                    showsVerticalScrollIndicator={true}
                                    legacyImplementation={false}

                                    data={item.runner_list}
                                    keyExtractor={(item, index) => index.toString()}
                                    renderItem={({ item }, index) =>
                                        <TouchableHighlight style={{ flex: 1, flexDirection: 'row' }} onPress={this.toggleModal} >
                                            <Image style={{ width: 50, height: 50 }} source={{ uri: item.imageurl }} />                                                
                                        </TouchableHighlight>}
                                >
                                </FlatList>
                            </Animated.View>
                        )}
                    />
                </View>
            </SafeAreaView>

            <Modal isVisible={this.state.isModalVisible}
                    backdropTransitionOutTiming={1}>
                <View style={{ flex: 1 }}>
                    <Text>Hello!</Text>
                    <Button title="Hide modal" onPress={this.toggleModal} />
                </View>
            </Modal>
        </>
    );
}
}

const styles = StyleSheet.create({
    centeredView: {
        flex: 1,
        justifyContent: "center",
    alignItems: "center",
    marginTop: 22
},
modalView: {
    margin: 20,
    backgroundColor: "white",
    borderRadius: 20,
    padding: 35,
    alignItems: "center",
    shadowColor: "#000",
    shadowOffset: {
        width: 0,
        height: 2
    },
    shadowOpacity: 0.25,
    shadowRadius: 3.84,
    elevation: 5
},
openButton: {
    backgroundColor: "#F194FF",
    borderRadius: 20,
    padding: 10,
    elevation: 2
},
textStyle: {
    color: "white",
    fontWeight: "bold",
    textAlign: "center"
},
modalText: {
    marginBottom: 15,
    textAlign: "center"
}
});

export default MeetingDisplay;

ATTEMPT 1

У меня была идея, что это может быть мое использование сторонней библиотеки каруселей под названием «response-native-snap-carousel», поэтому я попытался заменить ее на ужасно выглядящий вид прокрутки, и все мои плоские списки / элементы отображались в нем, но это не удалось увеличить задержку всплывающего окна, которая все еще составляла 2-3 секунды.

ATTEMPT 2

Я нашел что-то около lled компонентact.pure, который потенциально должен выполнять поверхностное сравнение состояния / реквизита и запускать повторный рендеринг только тогда, когда элементы / состояние действительно изменились, что может означать анимацию / поток пользовательского интерфейса, что бы ни вызывало проблему. Но не лучше (как на эмуляторе, так и на устройстве) по-прежнему долгая пауза, прежде чем модальное отображение

class MeetingDisplay extends React.PureComponent

ATTEMPT 4

Извлеките уравнение из плоского списка, поместив кнопку для запуска модального режима. за пределами плоского списка внизу страницы под нижней каруселью.

....</View>
            </SafeAreaView>

            <Modal                    
                visible={this.state.isModalVisible}
                backdropTransitionOutTiming={1}
            >
                <View style={{ flex: 1 }}>
                    <Text>Hello!</Text>
                    <Button title="Hide modal" onPress={this.toggleModal} />
                </View>
            </Modal>
            <Button title="Show modal" onPress={this.toggleModal} />                
        </>
    );....

Это не привело к улучшению или повышению производительности. Так что еще вызывает проблему. Это постоянный повторный рендеринг моих компонентов, вызванный интервалом? Таким образом, должен быть способ приостановить повторный рендеринг компонента, который я пропустил. Кто-нибудь?

...