简体   繁体   中英

Redux with async components in React Native

I am currently developing a React Native mobile application.

I want to show the data from a database in a FlatList but two problems have come up so far:

  1. I can't mapStateToProps if the data has not been fetched yet
  2. The FlatList component throws an error when it is loaded given that that the data is not shown yet

I have tried to create a loading prop that will be sent set as true as soon as the component is mounting and will 'unblock' the functions that require the data; however this has not worked so far.

import React, { Component } from "react";
import { View, Text, Button, FlatList } from "react-native";
import { connect } from "react-redux";

import { Spinner } from "../../common";
import { booksFetch } from "../../actions/BookshelfActions";

class BookshelfList extends Component {
  componentDidMount() {
    this.props.booksFetch(); // Gets the data from the website
  }

  addBookScreen = () => {
    this.props.navigation.navigate("bookshelfadd");
  };

  renderRow(book) {
    return (
      <View>
        <Text>{book.book_name}</Text>
      </View>
    );
  }
  renderList() {
    if (this.props.loading) {
      console.log("loading");
      return <Spinner />;
    }
    return (
      <FlatList // Shows the data on the screen. Will crash if there is no data
        data={this.props.booklist}
        renderItem={() => this.renderRow()}
        keyExtractor={(book) => book.uid}
      />
    );
  }

  render() {
    return (
      <View>
        {this.renderList()}
        <Button onPress={this.addBookScreen} title="Add Book" />
      </View>
    );
  }
}

const mapStateToProps = (state) => {
  if (!this.props.loading) {
    const user_books = _.map(state.bookshelf.booklist, (val, uid) => { // Maps the data to the state. Will crash if there is no data
      return { ...val, uid };
    });
  }

  return {
    booklist: user_books || null,
    loading: state.bookshelf.loading,
  };
};

export default connect(mapStateToProps, { booksFetch })(BookshelfList);```


You can (and should) default everything to empty arrays when the data is null (if you are expecting to receive an array):

_.map(state.bookshelf?.booklist || [], (val, uid) => ...)

Note, ? is only available depending on the version of the babel compiler. If you're using the latest version of React Native, it should work. If not, you'll have to do some more checks such as state.bookshelf && state.bookshelft.booklist || [] state.bookshelf && state.bookshelft.booklist || [] .

<FlatList
  data={this.props.booklist || []}
  ...
/>

You should always provide a default value or conditionally render if the data you receive might be null .

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM