Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why is child component not receiving updated value from parent in React Native?

When an arrow is clicked the Cart Item View needs to expand that particular view and collapse any others currently expanded. The item id of that product is passed to the parent component to update which view is to be expanded (active). Although, the id is being passed and set on the expandedItem property in the reducer this does not get updated to the child component (even though it's being passed as prop on the child component). When the child component is re-evaluated at the end the expandedViewItem is still 0, which is it's default value. Does anyone know how to get the child component to receive the updated expandedItem value? Why is it still 0??

PLEASE watch the video I made debugging this issue: https://youtu.be/qEgxqAyWDpY

Here is where the value is evaluated in the child component:

render () {

const isExpanded = product.id === this.props.expandedViewId;

Here is the entire child component class:

export default class CartProductItem extends Component {
    constructor(props) {
        super(props);
        this.state = {showCounter: false};
    }

    expandCartProductItem(id) {
        this.props.onExpandClick(id); 
        this.setState(this.state);
    }

    updateDisplay = (nextProps) => {
        // Null check is needed here as 0 is a valid value
        if (nextProps.activeIndex !== null && nextProps.activeIndex === this.props.index) {
            this.setState({
                showCounter: !this.state.showCounter
            });
        } else if (nextProps.activeIndex !== null && nextProps.activeIndex !== this.props.index) {
            this.setState({
                showCounter: false
            });
        }
    }

    componentWillReceiveProps(nextProps) {
        console.log('nextProps: ', nextProps)
    }

    render() {
        const serverUrl = getServerAddress();
        const {product} = this.props;
        const price = product.iogmodPrice ? product.iogmodPrice : product.price;

        const isExpanded = product.id === this.props.expandedViewId;

        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.expandCartProductItem(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>
        );
    }
}

Here is the parent component function that passes the id to the action and the initial const declarations in the render:

expandAndCollapseItems = (id) => {
    this.props.dispatch(collapseCartItemViews(id));
}

render() {
    const {isLoading, displayDetails, sortCasesAsc, details, items, expandedItem} = this.props.orderInfo;

Here is the child component in the parent component where the expandedItem variable is being passed into it:

<FlatList 
    data={items}
    keyExtractor={(item, index) => item.id.toString()}
    renderItem={({item}) => <CartProductItem product={item} expandedViewId={expandedItem} onExpandClick={(id) => this.expandAndCollapseItems(id)} />}
/>

Finally, here is the reducer function updates the app state:

    case types.SET_EXPANDED_STATE:
        const id = action.id;

        return {
            ...state,
            expandedItem: id
        }
like image 304
FairyQueen Avatar asked Aug 09 '18 20:08

FairyQueen


1 Answers

Since you're using redux, you can just grab the expanded item id from the redux store in the child instead of passing it down from the parent.

like image 61
Matt Aft Avatar answered Oct 01 '22 13:10

Matt Aft