1
votes

I have created a react parent component that passes some props down to it's child component, and holds an onClick function. The onClick function should console.log 'WORKED' when a Product component is clicked, this isn't working and nothings appearing on the console. I don't understand where I went wrong, this should be so simple. Have I made a stupid mistake I keep missing?

here is my parent component code:

import React from 'react';
import { connect } from 'react-redux';
import Product from '../components/product.js';
import { bindActionCreators } from 'redux';
import { changeTotal } from '../actions/index.js';
import { selectProduct } from '../actions/index.js';

class ProductList extends React.Component {
    constructor(props) {
        super(props);

        this.state={
            total: 0
        }

        this.addFromTotal = this.addFromTotal.bind(this);
        this.subtractFromTotal = this.subtractFromTotal.bind(this);
        this.handleClick = this.handleClick.bind(this);
    }

    handleClick() {
        console.log('done')
    }

    addFromTotal(product) {
        var x = Number(product.price)
        this.setState({total: this.state.total + x}, () => {
            console.log('total is ' + this.state.total);
            var total = this.state.total;
            this.props.changeTotal(total);
        });
    }

    subtractFromTotal(product) {
        var x = Number(product.price)
        this.setState({total: this.state.total - x}, () => {
            console.log('total is ' + this.state.total);
            var total = this.state.total;
            this.props.changeTotal(total);
        });
    }

    render() {
        var createProductList = this.props.products.map((product, i) => {
            return <Product
                    key={i} 
                    title={product.title} 
                    price={product.price} 
                    definition={product.definition}
                    source={product.source}
                    addFromTotal={() => this.addFromTotal(product)}
                    subtractFromTotal={() => this.subtractFromTotal(product)}
                    // onClick={() => this.props.selectProduct(product)}
                    onClick={this.handleClick}
                    />
        });
        return (
            <div>
                <div>Product List</div>
                <div style={{display: 'flex', flexDirection: 'row'}}>{createProductList}</div>
            </div>
        );
    }
}

function mapStateToProps(state) {
    return {
        products : state.products
    }
}

function mapDispatchToProps(dispatch) {
    return bindActionCreators({ changeTotal: changeTotal }, dispatch);
}


export default connect(mapStateToProps, mapDispatchToProps)(ProductList);

here is the code for the Product (child) component:

import React from 'react';
import { connect } from 'react-redux';
import { bindActionCreators } from 'redux';
import { updateItemObject } from '../actions/index.js'

class Product extends React.Component {
    constructor(props) {
        super(props);

        this.state = {
            counter: 0,
            itemTotal: 0
        }

        this.handleAdd = this.handleAdd.bind(this);
        this.handleSubtract = this.handleSubtract.bind(this);
    }

    handleAdd(product) {
        var x = Number(this.props.price)
        this.setState({
            itemTotal: this.state.itemTotal + x,
            counter: this.state.counter + 1
        }, () => {
            console.log('item total ' + this.state.itemTotal);
            console.log('item count ' + this.state.counter);
            this.props.addFromTotal(product);
        });
    }

    handleSubtract(product) {
        if(this.state.counter === 0) {
            return;
        }

        var x = Number(this.props.price)
        this.setState({
            itemTotal: this.state.itemTotal - x,
            counter: this.state.counter - 1
        }, () => {
            console.log('item total ' + this.state.itemTotal);
            console.log('item count ' + this.state.counter);
            this.props.subtractFromTotal(product);
        });
    }

    render() {
        return (
            <div style={{margin: '20px', backgroundColor: '#F5F5F5', cursor: 'pointer'}}>
               <div>product name: {this.props.title}</div>
               <div>product price: {this.props.price}</div>
               <div>product definition: {this.props.definition}</div>
               <div style={{
                   backgroundImage: this.props.source,
                   backgroundSize: 'cover',
                   padding: '15px',
                   margin: '15px',
                   height: '200px',
                   width: '250px' 
               }}>
               </div>
               <div>
                   <span style={{cursor: 'pointer'}} onClick={this.handleAdd}>+ </span>
                   <span style={{cursor: 'pointer'}} onClick={this.handleSubtract}>-</span>
               </div>
               <div>
                   <div>x{this.state.counter} {this.props.title} for a sum of {this.state.itemTotal}</div>
               </div>
            </div>
        );
    }
}

function mapDispatchToProps(dispatch) {
   return bindActionCreators({ updateItemObject: updateItemObject }, dispatch);
}

export default connect(null, mapDispatchToProps)(Product);
2
Show the code of Product component.Prakash Sharma
this isn't the reference you think it is, because of the lamba's lexical bindingSterling Archer
okay, I added the code for the product component!user74843
You don't use this.props.onClick anywhere in the child component - are you hoping that it would just work like if you have put an onClick on a div? Because it won't.Ben Hare

2 Answers

2
votes

You are not using the onClick prop passed to product component inside that component. Therefore it is not being fired. You have to assign the event handler to some element in product component, which will fire the method passed to it as prop something like this

// Product.js component
render() {
        return (
            <div onClick={this.props.onClick} style={{margin: '20px', backgroundColor: '#F5F5F5', cursor: 'pointer'}}>
      ....
1
votes

Your passing onClick as a prop from the parent component to the child component, but in the child component I didn't see that your calling props.onClick on some click event in the child component.