Reputation: 151
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
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
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