Reputation: 2373
When a cart item view is expanded all other cart item views need to be collapsed. The problem is my item view is a separate component that needs this information passed to it from the parent. When an arrow is clicked the item id is pass from the child component back to the parent component and then to the action and finally the reducer where the app state is updated. This triggers a re-render in the parent component but this does not trickle down to the child component where it is needed even though the property that got changed is being passed to the child. Does anyone know who to get this app state change to cause a re-render in the child component?
Here is my cart item view (child component). The isExpanded variable needs to get updated from the app state change in order to control which views should be expanded and collapsed.
componentWillReceiveProps(nextProps) {
console.log('nextProps: ', nextProps)
}
render() {
const serverUrl = getServerAddress();
const {product} = this.props;
const price = product.iogmodPrice ? product.iogmodPrice : product.price;
const isExpanded = this.props.expandedViewId === product.id;
const imageSrc = product.imageName
? 'https://b2b.martinsmart.com/productimages/'+ product.imageName.replace("Original", "Thumbnail")
: serverUrl + '/b2b/resources/images/nophoto.gif';
return (
<View style={styles.pContainer}>
<CartProduct
imageName={imageSrc}
name={product.description}
itemNum={product.id}
price={price}
pack={product.pack}
averageWeight={product.averageWeight}
cases={product.order_count}
/>
<TouchableOpacity style={styles.buttonContainer} onPress={() => this.props.onExpandClick(product.id)}>
{isExpanded ? <LineIcon name="arrow-up" style={styles.arrowIcon} /> : <LineIcon name="arrow-down" style={styles.arrowIcon} />}
</TouchableOpacity>
{isExpanded &&
<ExpandHeightView height={70}>
<View style={styles.counterContainerView}>
<QuantityCounter style={{width: '100%'}} product={product} />
</View>
</ExpandHeightView>
}
</View>
);
}
When an expand arrow is clicked the item id is passed back and sent to the action (parent view):
expandAndCollapseItems = (id) => {
this.props.dispatch(collapseCartItemViews(id));
}
The render line of the parent component:
render() {
const {isLoading, displayDetails, sortCasesAsc, details, items, expandedItem} = this.props.orderInfo;
Here is where the item that was click (to be expanded) gets passed in:
<FlatList
data={items}
keyExtractor={(item, index) => item.id.toString()}
renderItem={({item}) => <CartProductItem product={item} expandedViewId={expandedItem} onExpandClick={(id) => this.expandAndCollapseItems(id)} />}
/>
The cart action function:
export function collapseCartItemViews(id) {
return (dispatch, getState) => {
dispatch({
type: types.SET_EXPANDED_STATE,
id: id
});
}
}
The reducer function:
case types.SET_EXPANDED_STATE:
const id = action.id;
return {
...state,
expandedItem: id
}
Upvotes: 1
Views: 207
Reputation: 1176
In the TouchableOpacity
element that contains the arrow, try changing the onPress
function to this:
onPress={() => this.props.onExpandClick(product.id); this.setState(this.state);}
This should trigger a re-render when it is clicked.
Upvotes: 1