pythwan
pythwan

Reputation: 99

Why passing a function from a parent Class Component to a child Functional Component doesn't work?

I'm trying to pass a method from a parent class component in the props to a child functional component.

The parent component basically just sends data from the database to a functional component that 'draws' the component itself. Inside the functional component I have <option> and I want to console.log() the data from the functional component, which means, the handler of the change will be in the class component just passing it to the child functional component.

I read the way to do it in the ReactJS docs, but for some reason it doesn't work. No error, but nothing is printed to the console.

The parent class component:

export default class ProductCardComponent extends Component{


  constructor(props) {
      super(props)

      this.handleClick = this.handleClick.bind(this)
      this.onChangedColor = this.onChangedColor.bind(this)

      this.state = {
          product:  [],
          currentPage: 1,
          cardsPerPage: 9,

      }
  }


onChangedColor(e) {
    console.log("sup")
    console.log(e)
    alert("here")
}



render() {



    const renderCards = currentCard.map( (card, index) => {
            return <Col key={index}> <FunctionalProductCardComponent 
                                      product={card} 
                                      key={card._id} 
                                      onChange= {(e) => this.onChangedColor(e)} />
                    </Col>
        } );

        return (
        <div id="centeredRowForPagination">
            <div>
                <Row id="RowIdForCentering">
                    {renderCards}
                </Row>
            </div>
            <div id="centeredRowForPagination">
                <Row>
                        <Pagination id="page-numbers">
                                {renderPageNumbers}
                        </Pagination>
                </Row> 
            </div>
        </div>
    )
}
}

The child functional component:

const myRef = createRef()

const FunctionalProductCardComponent = props => {



var data = [];
for (let i = 0 ; i < props.product.color.length ; i++ ) { 
    data.push( {'value': props.product.color[i], 'label': props.product.color[i] } )
}
console.log(data)
return (
    // giving the div id only for design pourpse
<div id="ProductCard">
    <Col>
        <Card style={{ width: '18rem'}}>


            <Card.Img variant="top" src={imageUrl} id='ringImgId'/>

            <Card.Body>
                <Card.Title>Card Title</Card.Title>
                <Card.Text>

                    }
                    <tr><td>Name:    {props.product.name}</td></tr>
                    <tr><td>Price: {props.product.price}</td></tr>
                    <tr><td>Gender:  {props.product.gender}</td></tr>
                    <tr><td>Serial:  {props.product.serial}</td></tr>
                </Card.Text>
            </Card.Body>

                <Accordion>
                    {/* <Card> */}
                        <Card.Header>
                        <Accordion.Toggle className="accordionToggleButton" as={Button} variant="link" eventKey="0">
                            Size :
                        </Accordion.Toggle>
                        </Card.Header>
                        <Accordion.Collapse eventKey="0">
                            {/* <Card.Body> */}
                                <Select  ref={myRef} required className='form-control' options={props.product.size} placeholder ={'Select a color'} onChange={(selectedValue) => { props.onChange(()=>{{return selectedValue}}); }} />
                                    {/* <Select className="form-control" options={props.product.size} onChange= {(selectedValue) => {
                                        this.setState({value: selectedValue});
                                        this.props.onChange(() => {return selectedValue})
                                    }} 
                                    // value={this.state.value}
                                     /> */}
                            {/* </Card.Body> */}
                        </Accordion.Collapse>
                    {/* </Card> */}
                    {/* <Card> */}
                        <Card.Header>
                        <Accordion.Toggle className="accordionToggleButton" as={Button} variant="link" eventKey="1">
                            Color : 
                        </Accordion.Toggle>
                        </Card.Header>
                        <Accordion.Collapse eventKey="1">
                            <Card.Body>
                                <Select required className='form-control' options={data} placeholder ={'Select a color'} onChange={(selectedValue) => { props.onChange(()=>{{return selectedValue}}); }} />
                            </Card.Body>
                        </Accordion.Collapse>
                    {/* </Card> */}
                </Accordion>
                {/* () => {
      return selectedValue;
    } */}
            <Card.Body>
                <Card.Link href="#">Buy</Card.Link>
                <Card.Link id="addToCartBtn" href="#">Add To Cart</Card.Link>
            </Card.Body>


        </Card>
    </Col>
</div>

) }

export default FunctionalProductCardComponent;

it's now invoke the method, but doesn't pass the value.

Upvotes: 2

Views: 96

Answers (1)

Maf
Maf

Reputation: 725

In ProductCardComponent component:

onChange= {(e) => this.onChangedColor(e)}

should be replaced by

onChange ={(e)=> {this.onChangedColor(()=> {return e()})}} //e is a function

Then from FunctionalProductCardComponent, in

this.props.onChange(()=>{return selectedValue});

an anonymous function returns the value to be used by onChangedColor()

This is why its paramenter should be handled as a function:

onChangedColor(e) {
    console.log("sup")
    console.log(e()) //e is a function passed in FunctionalProductCardComponent
    alert("here")
}`

Upvotes: 1

Related Questions