Реакция асинхронной функции сбрасывает состояние в null после setState - PullRequest
0 голосов
/ 08 ноября 2018

Следующий код вернет ошибку для необработанного отклонения обещания 'cannot read property 'lastVisiblePost' of undefined при нажатии кнопки нумерации страниц.

Похоже, что он устанавливает состояние в ноль сразу после того, как делает начальное getPosts.

Работает при первом запуске, но в тот момент, когда вы нажмете кнопку, вызывающую состояние getPosts, будет равно null.

class App extends Component {
    state = {
        listState: 'top',
        allPosts: [],
        lastVisiblePost: null
    }

    async componentDidMount() {
        const { user } = await firebase.auth().signInAnonymously()

        this.getPosts()
    }

    async getPosts() {
        console.log(this.state)
        console.log(this.state.lastVisiblePost)
        let posts = null
        if (this.state.lastVisiblePost) {
            posts = await firebase.firestore()
                    .collection('posts')
                    .orderBy('likes')
                    .startAfter(last)
                    .limit(2)
                    .get()
        } else {
            posts = await firebase.firestore()
                    .collection('posts')
                    .orderBy('likes')
                    .limit(2)
                    .get()
        }
        let newPosts = []
        posts.forEach(post => {
            newPosts.push({
                id: post.id,
                data: post.data()
            })
        })

        console.log(posts.docs)
        console.log("memes", posts.docs[posts.docs.length - 1])

        this.setState({
            allPosts: newPosts,
            lastVisiblePost: posts.docs[posts.docs.length - 1]
        }, () => {
            console.log("doink", this.state)
        })
    }

    render() {
        const { listState, allPosts } = this.state

        return (
            <SafeAreaView style={styles.container}>
                { /* Logo */ }
                <View style={styles.logoContainer}>
                    <Image style={styles.logo} source={anywayLogo} />
                </View>
                { /* Top and New Buttons */ }
                <View style={styles.topAndNewContainer}>
                    <Text style={[styles.topAndNewText, listState === 'top' ? { color: 'red' } : { color: 'black' }]} onPress={() => this.setState({listState: 'top'})}>top</Text>
                    <Text style={[styles.topAndNewText, listState === 'new' ? { color: 'red' } : { color: 'black' }]} onPress={() => this.setState({listState: 'new'})}>new</Text>
                </View>
                { /* Feed */ }
                <View style={styles.feedContainer}>
                    {
                        allPosts.map(post => {
                            return (<Text key={post.id}>{post.data.title}</Text>)
                        })
                    }
                </View>
                <Button title="Next page" onPress={this.getPosts} />
            </SafeAreaView>
        );
    }
}

Асинк ждет, чтобы сломать мое состояние?

Ответы [ 2 ]

0 голосов
/ 08 ноября 2018

Это потому, что ваша функция getPosts неправильно привязана к вашему компоненту, поэтому this относится к функции getPosts, а не к вашему компоненту. Поскольку он не имеет какого-либо свойства состояния, вы получите сообщение об ошибке.

Есть два способа сделать это, либо связать в конструкторе:

class App extends Component {
  constructor(props){
    super(props)
    this.state = {
      listState: 'top',
      allPosts: [],
      lastVisiblePost: null
    }

    this.getPosts = this.getPosts.bind(this)
  }
}

Или вы используете transform-class-properties плагин babel, и затем вы можете объявить методы компонентов как функции стрелок, которые не предоставляют свои this, поэтому ключевое слово this будет автоматически ссылаться на ваш компонент:

getPosts = async () => {
  //your code
}
0 голосов
/ 08 ноября 2018

Вам нужно установить состояние в конструкторе, иначе оно не будет определено в остальных ваших функциях.

constructor(props) {
   super(props);
   this.state = {
    listState: 'top',
    allPosts: [],
    lastVisiblePost: null
   }
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...