Переход к другому экрану из элемента плоского списка

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

Код, который у меня здесь, работал пару дней, но теперь это не так, сразу же, когда приложение загружается, EventDetailScreen открывается даже до того, как я нажму на любой из элементов плоского списка, а затем, когда я нажму кнопку «Назад» из EventDetailScreen, который возвращает меня к EventListScreen, если я нажму на любой из элементов списка, ничего не произойдет, и я не попаду на EventDetailScreen.

Я также получаю сообщение об ошибке:

Предупреждение: нельзя обновлять во время существующего перехода состояния (например, в render или конструкторе другого компонента). Методы рендеринга должны быть чистой функцией свойств и состояния; побочные эффекты конструктора являются анти-шаблоном, но их можно переместить в componentWillMount.

Я новичок в React Native, поэтому любая помощь будет очень признательна!

Я использую: "react-navigation": "^2.7.0", "react": "16.4.1", "react-native": "0.56.0",

Я использовал этот ответ Переход к каждому элементу в FlatList на SO, чтобы заставить его работать первоначально.

EventListScreen.js

export default class EventListScreen extends Component {

constructor() {
    super();
    this.ref = firebase.firestore();
    this.unsubsribe = null;

    this.state = {
        eventName: '',
        eventLocation: '',
        loading: true,
        events: [],
    };
}

componentDidMount() {
    console.log('EventsListScreen1');
    this.unsubsribe = this.ref.onSnapshot(this.onCollectionUpdate)
}

componentWillUnmount() {
    this.unsubsribe();
}


openDetails = () => {
    this.props.navigation.navigate('EventDetailScreen');
};

render() {

    if (this.state.loading) {
        return null;
    }

    return (
        <Container>

            <FlatList
                data={this.state.events}
                // Get the item data by referencing as a new function to it
                renderItem={({item}) =>
                    <Event
                    openDetails={() => this.openDetails()}
                    {...item} />}
            />

            <View style={{flex: 1}}>
                <Fab
                    active={this.state.active}
                    direction="left"
                    containerStyle={{}}
                    style={{backgroundColor: '#5067FF'}}
                    position="bottomRight"
                    onPress={() => 
                    this.props.navigation.navigate('EventForm')
                    }>
                    <Icon 
                       name="ios-add"/>
                </Fab>
            </View>

        </Container>
    );
}

Event.js

export default class Event extends Component {

render() {

    return (
        <Card>
            <CardSection>
                <Text>{this.props.eventName}</Text>
            </CardSection>

            <TouchableOpacity
              onPress={this.props.openDetails()}
            >
            <CardSection>
                <Image
                    style={{
                       width: 350,
                       height: 300
                    }}
                    source={{
                       uri: this.props.imageDownloadUrl
                    }}
                />
            </CardSection>

            <CardSection>
                <Text>{this.props.eventLocation}</Text>
            </CardSection>
            </TouchableOpacity>
        </Card>
    );
}};

EventDetailScreen.js

export default class EventDetailScreen extends Component {
render() {
    /* 2. Get the param, provide a fallback value if not available */
    const { navigation } = this.props;
    const itemId = navigation.getParam('itemId', 'NO-ID');

    return (
        <View 
           style={{ 
              flex: 1,
              alignItems: 'center',
              justifyContent: 'center' 
            }}>
            <Text>Details Screen</Text>
        </View>
    );
}}

person Andrew Irwin    schedule 03.09.2018    source источник


Ответы (1)


Вероятно, это из-за следующей строки в компоненте Event.

<TouchableOpacity
    onPress={this.props.openDetails()} // <-- this line to be specific
 > ... </>

Как только EventScreenList отображает список, первая строка выполняет метод openDetails(), который переключает экран.

Вы можете избежать этого, используя onPress={() => this.props.openDetails()}.

Также неплохо иметь следующее в конструкторе или компоненте componentDidMount компонента EventScreenList, потому что обе функции используют this контекст оператора.

this.openDetails = this.openDetails.bind(this);
this.onCollectionUpdate = this.onCollectionUpdate.bind(this);

Чтобы проверить значение приведенного выше утверждения, попробуйте

<TouchableOpacity
    onPress={this.props.openDetails} // <-- this line
 > ... </>

Предупреждающее сообщение связано с навигацией до завершения обновления состояния.

person Priyesh Kumar    schedule 03.09.2018
comment
Большое спасибо. Не могли бы вы объяснить мне подробнее, почему добавление двух вышеуказанных методов в конструктор или componentDidMount является хорошей идеей? есть ли какие-нибудь учебники, которые вы могли бы порекомендовать, спасибо - person Andrew Irwin; 03.09.2018
comment
@Priyesh пытается объяснить, что вы должны привязать к этому функции. Я не уверен, действительно ли вам нужно привязать его, потому что вы используете функции стрелок, которые автоматически привязывают вашу область к этому - person Nino9612; 04.09.2018
comment
@AndrewIrwin, вы можете прочитать этот вопрос более подробно. stackoverflow.com/questions/45998744/ - person Priyesh Kumar; 04.09.2018