Passing a function through three levels of components (i.e. calling a function from a grandchild component)

kojow7

I want to pass an item id from either a Child component or grandchild component, but cannot figure out how to do so. Other examples I have looked at show using the arrow function to achieve this, but for whatever reason my function is not getting called.

I have the following in Parent.js:

chosenItem(id){
    console.log("CHOSEN ITEM SELECTED")
    this.setState({
        chosen_item: id
    })
}

and in the Parent.js render function:

<Child objects={objects} chosenItem={() => this.chosenItem()} />

Then in my Child.js I have:

items = this.props.objects.items.map(item => {
    return (
        <ClickableTextComponent
            key={item.id}
            text={item.label}
            onClick={item =>this.props.chosenItem(item.id)}
         />
     )
 })

In my Child.js render function I have:

{items}

I also wasn't sure whether the actual click event should go inside of the Child.js or the ClickableTextComponent. Or does it really matter? Currently I have placed it in the Child.js component as seen above.

What am I doing wrong? How can I modify my code so that the function gets called? I have read a bit about currying to prevent a function from being recreated multiple times. Is that necessary in this case? If so, where and how should I be implementing it. In my Parent or Child components?

Update

I was previously trying to get the onClick to work from Child.js, but as it needs to be attached to a div I have moved it to ClickableTextComponent (the grandchild component).

One issue with ClickableTextComponent is that I want to be able to set the state when the component is clicked so that I can turn the component a different colour. Because of that I am needing to use a function to then call the chosenItem function. So here is what I have in my `ClickableTextComponent.js':

handleClick(){
    this.setState({
        text_state: "clicked"
    })
    this.props.chosenItem()
}

In the render I then have:

<div
    onClick={this.handleClick.bind(this)}
    onMouseOver={this.changeTextState.bind(this, "hover")}
    onMouseOut={this.changeTextState.bind(this, "default")}
>{this.props.text}</div>

New Error

Based on the above changes, I am now getting this.props.chosenItem is not a function. However, I cannot figure out why it is giving me this error. I can see the function name when I display this.props to the console. What am I doing wrong?

Tolsee

The answer given by Kevin He holds true. But there is one problem with that solution.

<Child objects={objects} chosenItem={(x) => this.chosenItem(x)} />

When you do such, every time your parent is rerendered. It will create a new instance of the function. And, your child component also rerenders because It sees the props changing.

Best solution is:

<Child objects={objects} chosenItem={this.chosenItem} />

Update:

Now, it seems to make sense.

The problem is again with ClickableTextComponent.

Here is the update ClickableTextComponent which works.

https://codesandbox.io/s/73x6mnr8k0

The main problem:

items = this.props.objects.items.map(item => {
    return (
        <ClickableTextComponent
            key={item.id}
            text={item.label}
            onClick={item =>this.props.chosenItem(item.id)}
         />
     )
 })

//
// Here you made a function (item) => this.props.choseItem(item.id)
// That means when you call that function you should call like this
// i.e. passing parameter needed for the function
// 

handleClick(){
    this.setState({
        text_state: "clicked"
    })
    this.props.chosenItem(item)
}

//
// But do you do not have the item in the children
// Parent should be changed as below
//

items = this.props.objects.items.map(item => {
    return (
        <ClickableTextComponent
            key={item.id}
            text={item.label}
            onClick={() =>this.props.chosenItem(item.id)}
         />
     )
 })

//
// Now you made a fuction () => this.props.chosenItem(item.id)
// The main difference being you are not taking a item as parameter
// item will be taken from outer scope that means, item from map
//

// 
// Another solution can be
// 

items = this.props.objects.items.map(item => {
    return (
        <ClickableTextComponent
            key={item.id}
            id={item.id}
            text={item.label}
            onClick={this.props.chosenItem}
         />
     )
 })

// And in ClickableTextComponent

handleClick(){
    this.setState({
        text_state: "clicked"
    })
    this.props.chosenItem(this.props.id)
}

Collected from the Internet

Please contact [email protected] to delete if infringement.

edited at
0

Comments

0 comments
Login to comment

Related

Passing Event Handler From Grandparent to GrandChild Component in Reactjs

Calling components function from iframe

Passing a function to Child Component through a Prop using ReactJS

Calling a Cloud Function from Android through Firebase

angular 5 - "this" refers to Directive instead of Component, when passing a function from component to directive through @Input

calling grandparent method from grandchild functional component in react

Calling a python function from R with passing the arguments

React - calling function from a sibling component

Calling a function and passing arguments from Kotlin to Flutter

Passing function prop to child component (via Link and Route components)

passing index and calling a function through dropzone.js

Postgresql calling a function in another function passing an argument from the main function

Calling function in main file from component

Calling another function through eval by passing arguments in Perl

passing results from indexeddb transaction to calling function

Calling component function from template

React with Redux: Passing function to child component, calling without handler in child

Passing a function to React Component and then calling it causes "Uncaught TypeError: x is not a function"

How Can I pass a function in grandparent component to grandchild components in ReactJs?

React typescript passing function as prop and calling from child component

calling function from child to child component

Passing state from parent component to child function

How can I call a function in a component from other components in React?

Passing function through Switch Route component

calling grandparent method from inside the grandchild component

Calling/passing variables from a function to function

Passing a function from useReducer state to the component that needs it

How can I loop a function through every combination of levels of a factor?

Passing a function down two components as a prop and it returns as undefined in the destination component

TOP Ranking

  1. 1

    Failed to listen on localhost:8000 (reason: Cannot assign requested address)

  2. 2

    Loopback Error: connect ECONNREFUSED 127.0.0.1:3306 (MAMP)

  3. 3

    How to import an asset in swift using Bundle.main.path() in a react-native native module

  4. 4

    pump.io port in URL

  5. 5

    Compiler error CS0246 (type or namespace not found) on using Ninject in ASP.NET vNext

  6. 6

    BigQuery - concatenate ignoring NULL

  7. 7

    ngClass error (Can't bind ngClass since it isn't a known property of div) in Angular 11.0.3

  8. 8

    ggplotly no applicable method for 'plotly_build' applied to an object of class "NULL" if statements

  9. 9

    Spring Boot JPA PostgreSQL Web App - Internal Authentication Error

  10. 10

    How to remove the extra space from right in a webview?

  11. 11

    java.lang.NullPointerException: Cannot read the array length because "<local3>" is null

  12. 12

    Jquery different data trapped from direct mousedown event and simulation via $(this).trigger('mousedown');

  13. 13

    flutter: dropdown item programmatically unselect problem

  14. 14

    How to use merge windows unallocated space into Ubuntu using GParted?

  15. 15

    Change dd-mm-yyyy date format of dataframe date column to yyyy-mm-dd

  16. 16

    Nuget add packages gives access denied errors

  17. 17

    Svchost high CPU from Microsoft.BingWeather app errors

  18. 18

    Can't pre-populate phone number and message body in SMS link on iPhones when SMS app is not running in the background

  19. 19

    12.04.3--- Dconf Editor won't show com>canonical>unity option

  20. 20

    Any way to remove trailing whitespace *FOR EDITED* lines in Eclipse [for Java]?

  21. 21

    maven-jaxb2-plugin cannot generate classes due to two declarations cause a collision in ObjectFactory class

HotTag

Archive