首页 > 解决方案 > react js中的绑定函数

问题描述

我以两种方式绑定函数,第一种工作正常,但在 return 方法中使用 es6 函数语法是一种不好的方法,因为它在每个实例上调用一个新方法,所有代码都工作正常,我只需要帮助绑定功能。return 语句中的绑定工作正常。

import React, { Component } from 'react';
import './ColorBox.css';

export default class ColorBox extends Component{
    //Constructor
    constructor(props){
        super(props);
        this.state = { copied: false};
    }
    
    // Not binded because its called inside the binded function, althrough it doesnot matter
    changeCopyState(){ 
        this.setState({ copied: true}, () => (
            setTimeout(() => (
                this.setState({copied: false})
            ), 1500)
        ))
    }

    // Function to copy color code to clipboard
    copyToClipBoard(str) {
        const element = document.createElement('textarea');
        element.value = str;
        document.body.appendChild(element);//insert textarea into html body
        element.select();
        document.execCommand('copy');//internal command to copy from text area
        document.body.removeChild(element);//remove after coping command
        this.changeCopyState();
    }

    render(){
        let {name, background} = this.props;
        let {copied} = this.state;  
        return (
            <div style={{ background}} className="ColorBox">
                <div style={{ background }} className={`copy-overlay ${ copied && "show"}`} /> 
                    <div className="box-content">
                        <span>{name}</span>
                    </div>
                    <button className="copy-button" onClick={() => this.copyToClipBoard(background)}>Copy</button>
                <span className="more-shades">More</span>
            </div>
        )
    }
}

现在如果我尝试在构造函数中绑定函数,它会给我一个超出调用函数限制等的错误,为什么会发生这种行为。

import React, { Component } from 'react';
import './ColorBox.css';

export default class ColorBox extends Component{
    //Constructor
    constructor(props){
        super(props);
        this.state = { copied: false};
        this.copyToClipBoard = this.copyToClipBoard.bind(this);
    }
    
    // Not binded because its called inside the binded function, althrough it doesnot matter
    changeCopyState(){ 
        this.setState({ copied: true}, () => (
            setTimeout(() => (
                this.setState({copied: false})
            ), 1500)
        ))
    }

    // Function to copy color code to clipboard
    copyToClipBoard(str) {
        const element = document.createElement('textarea');
        element.value = str;
        document.body.appendChild(element);//insert textarea into html body
        element.select();
        document.execCommand('copy');//internal command to copy from text area
        document.body.removeChild(element);//remove after coping command
        this.changeCopyState();
    }

    render(){
        let {name, background} = this.props;
        let {copied} = this.state;  
        return (
            <div style={{ background}} className="ColorBox">
                <div style={{ background }} className={`copy-overlay ${ copied && "show"}`} /> 
                    <div className="box-content">
                        <span>{name}</span>
                    </div>
                    <button className="copy-button" onClick={this.copyToClipBoard(background)}>Copy</button>
                <span className="more-shades">More</span>
            </div>
        )
    }
}

标签: javascriptreactjsperformance

解决方案


问题

onClick={this.copyToClipBoard(background)}立即调用回调,从而导致您看到的渲染循环。

解决方案

  1. 转换copyToClipBoard为 curried 函数,以便它使用一个background参数,在范围内关闭,并返回一个用作回调的函数。

    // Function to copy color code to clipboard
    copyToClipBoard(str) {
      return () => {
        const element = document.createElement('textarea');
        element.value = str;
        document.body.appendChild(element); //insert textarea into html body
        element.select();
        document.execCommand('copy'); //internal command to copy from text area
        document.body.removeChild(element); //remove after coping command
        this.changeCopyState();
      };
    }
    

    用法:

    <button
      className="copy-button"
      onClick={this.copyToClipBoard(background)} // <-- returns callback handler
    >
      Copy
    </button>
    
  2. 转换copyToClipBoard为 curried 箭头函数,因此this会自动绑定,您不需要在constructor.

    // Function to copy color code to clipboard
    copyToClipBoard = (str) => () => {
      const element = document.createElement('textarea');
      element.value = str;
      document.body.appendChild(element); //insert textarea into html body
      element.select();
      document.execCommand('copy'); //internal command to copy from text area
      document.body.removeChild(element); //remove after coping command
      this.changeCopyState();
    };
    

    用法:

    <button
      className="copy-button"
      onClick={this.copyToClipBoard(background)} // <-- returns callback handler
    >
      Copy
    </button>
    
  3. background已经在 中可用props,只需从那里使用它。

    // Function to copy color code to clipboard
    copyToClipBoard(str) {
      const { background } = this.props; // <-- destructure from props
    
      const element = document.createElement('textarea');
      element.value = background; // <-- use background
      document.body.appendChild(element); //insert textarea into html body
      element.select();
      document.execCommand('copy'); //internal command to copy from text area
      document.body.removeChild(element); //remove after coping command
      this.changeCopyState();
    }
    

    用法:

    <button
      className="copy-button"
      onClick={this.copyToClipBoard} // <-- just attach handler
    >
      Copy
    </button>
    

推荐阅读