简体   繁体   中英

pass props with functional component without declaring function within component

I iterate over a list of items and want to call a function onClick(). Example below:

class App extends Component {
    state = { items: [1, 2, 3, 4] };

    click = i => console.log(i);

    render() {
        return (
            <div>
                {this.state.items.map(item => (
                    <div 
                        key={item} 
                        // this works fine, but I rather not declare functions within the render function / JSX
                        onClick={() => this.click(item)}
                    >
                        {`click on # ${item}`}
                    </div>
                ))}
            </div>
        )
    }
}

As you can see, I declare a function in the JSX. I do this over and over, but some time ago I learned that you should avoid declaring a function within the component JSX itself, for performance reasons.

Is this true, also for functional components? And if so, is there any other way to pass dynamic information (item, in this case) to a callback?

NOTE: I'm looking forward to using hooks at some point, but right now I just want to know a best practice without using them.

NOTE II: That being said, if you are sure that this is a relevant problem and it could not be solved until now because of hooks, I obviously would like to learn that :)

Is this true, also for functional components?

Well actually there is no functional component used in your code. And everything you do in a function that gets called very often ( render() for example) causes performance to decrease, no matter wether that is a function or variable declaration or invokation. Wether that decrease matters is another thing.

And if so, is there any other way to pass dynamic information (item, in this case) to a callback?

You could .bind(...) it:

 onClick = {console.log.bind(console, item) }

but really, did you notice any delay on a rerender? Probably not, and if so that is not caused by the function declaration. Write code that looks beautiful to you, don't optimize for the compiler, let the compiler do that.

but some time ago I learned that you should avoid declaring a function within the component JSX itself

You shouldn't really avoid it, rather prefer other ways if possible. In this case there is not really a better way so go with it.

You can declare another method like this. Don't forget to use .bind . Otherwise, the method won't be called correctly.

class App extends Component {
    state = { items: [1, 2, 3, 4] };

    handleClick(item) {
        // do something
        console.log(item);
    }
    render() {
        return (
            <div>
                {this.state.items.map(item => (
                    <div 
                        key={item} 
                        // this works fine, but I rather not declare functions within the render function / JSX
                        onClick={this.handleClick.bind(this, item)}
                    >
                        {`click on # ${item}`}
                    </div>
                ))}
            </div>
        )
    }
}

You can create a parent component which will be responsible for looping through the items and passing the click handler down as a prop to each individual child component.

Then inside the child component you can easily reference the handler as this.props.onClick

Functions (objects) are passed by reference in JavaScript. By declaring it in the parent scope it will only take up space there. If initialized in the child, it will create space in memory for the function with each child component.

class Parent extends Component {
    state = { items: [1, 2, 3, 4] };

    parentClick(item) {
        // do something
        console.log(item);
    }
    render() {
        return (
            <div>
                {this.state.items.map(item => (
                  <Child item={item} onClick={this.parentClick}>
                ))}
            </div>
        )
    }
}



class Child extends Component {

    childClick(item) {
        this.props.onClick(item)
    }

    render() {
        return (
            <div>
                <p onClick={this.childClick(this.props.item)}>this.props.item</p>
            </div>
        )
    }
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM