【问题标题】:Loading Data from API into listview on react native via redux通过redux将数据从API加载到listview上
【发布时间】:2018-07-13 08:33:52
【问题描述】:

我想使用 RN 创建一个简单的应用程序,它只是从 API 数据加载列表视图。 这个想法是:

  • 我从我的 Action 中获取 API,然后将其传递给有效负载上的 reducer
  • 在 reducer 上,我将数据传递到我的组件中
  • 在我的组件上,我在 componentWillMount 上执行 getData 函数
  • 然后,在它加载后,我将使用此数据设置我的 listView 的 dataSource

但问题是,数据不会加载。它在调用 componentWillMount 时加载,但我不知道如何更新我的组件或如何检测在 componentWillMount 中的 getData 完成任务后创建的新道具。

这是我的代码 sn-p 1) ProductCategoryAction.js

export const getProductCategory = () => {
    return (dispatch) => {
        dispatch({ type: GET_PRODUCT_CATEGORY });

    fetch(CONFIG_GET_PRODUCT_CATEGORY_API)
        .then((response) => response.json())
        .then((responseJson) => getProductCategorySuccess(dispatch, responseJson.result))
        //.then((responseJson) => console.log(responseJson.result))
        .catch(() => getProductCategoryFail(dispatch));
}
};



const getProductCategorySuccess = (dispatch, product_categories) => {
    dispatch({
        type: GET_PRODUCT_CATEGORY_SUCCESS,
        payload: product_categories
    });
};
const getProductCategoryFail = (dispatch) => {
    dispatch({ 
        type: GET_PRODUCT_CATEGORY_FAIL
    });
};

2) ProductCategoryReducer.js

export default (state=INITIAL_STATE, action) => {

console.log(action);

switch(action.type) {
    case GET_PRODUCT_CATEGORY:  
        return { ...state, loading: true, error:'' };
    case GET_PRODUCT_CATEGORY_SUCCESS:  
        return { ...state, ...INITIAL_STATE, product_categories: action.payload };
    case GET_PRODUCT_CATEGORY_FAIL:  
        return { ...state, error: 'Couldn\'t load category data.', loading: false };
    default: 
        return state;
}
};

3) ProductCategoryList.js

class ProductCategoryList extends Component {
    componentWillMount() {
        this.props.getProductCategory();


    const ds = new ListView.DataSource({
        rowHasChanged: (r1, r2) => r1 !== r2
    });

    this.dataSource = ds.cloneWithRows(this.props.product_categories);
}

componentDidMount() {

    console.log(this.props);

    const ds = new ListView.DataSource({
        rowHasChanged: (r1, r2) => r1 !== r2
    });

    this.dataSource = ds.cloneWithRows(this.props.product_categories);

}

renderRow(product_category) {
    return <ProductCategoryListItem item={product_category} />
}

render() {
    if(this.props.loading) {
        return (
            <Spinner size="small" />
        );
    }
    if(this.props.error) {
        return (
            <View style={styles.errorWrapperStyle}>
                <Text style={styles.errorTextStyle}>{this.props.error}</Text>
            </View>
        );
    }
    return (
        <ListView
            dataSource={ this.dataSource }
            renderRow={ this.renderRow }
            enableEmptySections={ true }
        />
    );
}
}

const styles = StyleSheet.create({
    errorTextStyle: {
        fontSize: 14,
        alignSelf: 'center',
        color: 'red'
    },
    errorWrapperStyle: {
        backgroundColor: '#999999',
        padding: 2
    }
});

const mapStateToProps = ({ productCategories }) => {    
    const { product_categories, error, loading } = productCategories;
    return { product_categories, error, loading }
}

export default connect(mapStateToProps, { getProductCategory })(ProductCategoryList);

【问题讨论】:

    标签: listview react-native redux


    【解决方案1】:

    首先你应该了解React Component life cycle

    您正试图从 componentWillMount 中的 api 获取数据,但是当 componentDidMount 生命周期满足您创建 dataSource 变量的位置时,数据仍在获取。所以你没有得到任何数据源。

    删除您的componentDidMount 函数并像这样更改渲染函数,这样每当您获得product_categories 时,都会生成数据源。

    render() {
        let {loading, error, product_categories} = this.props;
    
        if(error) {
            return (
                <View style={styles.errorWrapperStyle}>
                    <Text style={styles.errorTextStyle}>{error}</Text>
                </View>
            );
        }
    
        if(product_categories & !loading){
            const ds = new ListView.DataSource({rowHasChanged: (r1, r2) => r1 !== r2});
    
            this.dataSource = ds.cloneWithRows(product_categories);
    
            return (
               <ListView
                   dataSource={ this.dataSource }
                   renderRow={ this.renderRow }
                   enableEmptySections={ true }
               />
            );
        }
        return (
            <Spinner size="small" />
        );
    }
    

    【讨论】:

    • 嗨 Lasitha,产品类别正在返回 [object Object],[object Object],... 它不会进入 if(product_categories & !loading) 部分。
    • 我通过删除 product_categories 来修复它,只使用 !loading if only
    • @baycisk 太棒了!
    【解决方案2】:

    props更新后是否需要调用componentWillReceiveProps

    componentWillReceiveProps(nextProps){
     this.loadPosts(nextProps)**HERE YOU CAN GET UPDATED PROPS**
    },
    

    当你当时的数据更新时,你可以在 nextprops 中访问这些数据

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2017-10-24
      • 1970-01-01
      • 2019-06-30
      • 2012-12-31
      • 1970-01-01
      相关资源
      最近更新 更多