baycisk
baycisk

Reputation: 151

Loading Data from API into listview on react native via redux

I wanted to create a simple App using RN, that just to load listview from API data. the idea is:

But the problem is, the data wont loaded. its loaded upon calling in componentWillMount, but I cant figure out how to update my component or how to detect new props that created after the getData in componentWillMount finished it task.

this is my code snippet

// 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);

Upvotes: 0

Views: 558

Answers (2)

Lasithe
Lasithe

Reputation: 2760

First you should get the understanding of React Component life cycle.

You are trying to fetch data from an api in componentWillMount, but the data is still fetching when componentDidMount life cycle has met where you create the dataSource variable. So you don't get any dataSource.

Remove your componentDidMount function and change the render function like this so whenever you get product_categories, the dataSource will get generated.

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" />
    );
}

Upvotes: 1

HpDev
HpDev

Reputation: 2927

Is it necessary to call componentWillReceiveProps after the props have updated

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

when you data update at that time , you can access those data in nextprops

Upvotes: 0

Related Questions