【问题标题】:React executing delegate passed to child via props通过道具传递给孩子的反应执行委托
【发布时间】:2019-03-12 20:17:03
【问题描述】:

我有一个反应组件,当单击按钮时会插入到页面中。该组件有一个按钮,单击时应执行onUpdateClient。它没有执行,我不知道为什么...我完全不知所措...此外,我通过props 将委托传递给该组件,并且我想从上述方法执行委托...我希望一旦我让事件处理程序工作,这也将工作...有人可以调出他们看到的任何可能阻止此事件处理程序触发的错误吗?

class UserProfile extends Component {
  constructor(props){
    super(props);
    this.state={
      updateDisabled : false
    };
    this.onUpdateClient = this.onUpdateClient.bind(this);
  }

    onUpdateClient(){
    // tried to execute this way... but this method isn't even getting called... i dont understand :*(
    //const {updateClientCallback} = this.props;
    alert("in " + this.props.client.name);
    this.setState({updateDisabled: true});
    //updateClientCallback();
  }
  
  render() {
const {classes, client, updateClientCallback} = this.props;

return (
    <div>
      <GridContainer>
        <GridItem xs={12} sm={12} md={16}>
          <Card>
            <CardHeader color="rose" icon>
              <CardIcon color="rose">
                <PermIdentity/>
              </CardIcon>
              <h4 className={classes.cardIconTitle}>
                Edit Profile - <small>{client.name} : {client.id}</small>
              </h4>
            </CardHeader>
            <CardBody>
              //{...}
              <Button disabled={this.state.updateDisabled} onclick={this.onUpdateClient.bind(this)} color={updateClientCallback == null? "error" : "warning"}
                      className={classes.updateProfileButton}>
                Update Profile
              </Button>
              <Clearfix/>
            </CardBody>
          </Card>
        </GridItem>
      </GridContainer>
    </div>
);
  }

这是实例化上述组件的组件

class Clients extends React.Component {
    constructor(props) {
        super(props);
        this.state = {
            data: dataTable.dataRows.map((prop, key) => {
                return {
                    id: key,
                    name: prop[0],
                    position: prop[1],
                    office: prop[2],
                    age: prop[3],
                    actions: (
                        // we've added some custom button actions
                        <div className="actions-right">
                            <Button
                                justIcon
                                round
                                simple
                                color="primary"
                                className="edit"
                            >
                                <Person/>
                            </Button>{" "}
                            {/* use this button to add a edit kind of action */}
                            <Button
                                justIcon
                                round
                                simple
                                onClick={this.editClient.bind(this,key)}
                                color="success"
                                className="edit"
                            >
                                <Dvr/>
                            </Button>{" "}
                        </div>
                    )
                };
            }),
            alert: null,
            show: false,
            client: null,
        };
        this.editClient = this.editClient.bind(this);
        this.viewClient = this.viewClient.bind(this);
    }

    removeClient() {
        alert(this.state.client.name);
        this.setState({client : null})
    }

    editClient(key) {
        let client = this.state.data.find(o => o.id === key);
        this.setState({
            client: (
                <UserProfile {... this.props} updateClientCallback={this.removeClient.bind(this)} client={client}/>
            )
        });
    }

    viewClient() {

    }

    inputConfirmAlert(e) {
        this.setState({client: e});
    }

    hideAlert() {
        this.setState({
            alert: null
        });
    }

    render() {
        const {classes} = this.props;
        return (
            <div>

                {this.state.client}
                <GridContainer>
                    <GridItem xs={12}>
                        <Card>
                            <CardHeader color="primary" icon>
                                <CardIcon color="primary">
                                    <People/>
                                </CardIcon>
                                <h4 className={classes.cardIconTitle}></h4>
                            </CardHeader>
                            <CardBody>
                                <ReactTable
                                    data={this.state.data}
                                    filterable
                                    columns={[
                                        {
                                            Header: "Name",
                                            accessor: "name"
                                        },
                                        {
                                            Header: "Position",
                                            accessor: "position"
                                        },
                                        {
                                            Header: "Office",
                                            accessor: "office"
                                        },
                                        {
                                            Header: "Age",
                                            accessor: "age"
                                        },
                                        {
                                            Header: "Actions",
                                            accessor: "actions",
                                            sortable: false,
                                            filterable: false
                                        }
                                    ]}
                                    defaultPageSize={10}
                                    showPaginationTop
                                    showPaginationBottom={false}
                                    className="-striped -highlight"
                                />
                            </CardBody>
                        </Card>
                    </GridItem>
                </GridContainer>
            </div>
        );
    }
}

【问题讨论】:

  • 你绑定onUpdateClient两次?

标签: reactjs delegates components


【解决方案1】:

我猜罪魁祸首在这里:

onclick={this.onUpdateClient.bind(this)}

这个位有一些问题:

  • 应该是onClick 而不是onclick
  • 您将绑定onUpdateClient 两次,分别在构造函数内部和事件处理程序内部。

所以我建议 2 个可能的修复方法:

class UserProfile extends Component {
  constructor(props){
    super(props);
    this.onUpdateClient = this.onUpdateClient.bind(this);
  }

  onUpdateClient(){
    // Your code here
  }

  render() {
    return (
      <div>
        <Button onClick={this.onUpdateClient}>
          Update Profile
        </Button>
      </div>
    );
  }
}

或者

class UserProfile extends Component { 
  onUpdateClient(){
    // Your code here
  }

  render() {
    return (
      <div>
        <Button onClick={this.onUpdateClient.bind(this)}>
          Update Profile
        </Button>
      </div>
    );
  }
}

编辑:第一个修复更可取,因为事件处理程序在渲染中被重用,因此给您的应用程序带来小的性能提升(取决于组件的实际成本)。第二种方法在每次组件重新渲染时都会创建一个新函数,从长远来看这显然会减慢您的应用程序

忘了说,如果安装了 JS 转译器,这个语法也是可以的:

class UserProfile extends Component { 
  onUpdateClient = () => {
    // Your code here
  }

  render() {
    return (
      <div>
        <Button onClick={this.onUpdateClient}>
          Update Profile
        </Button>
      </div>
    );
  }
}

看起来漂亮整洁,不是吗? :)

如需进一步参考,请访问React docs

【讨论】:

  • 请不要这样做:&lt;Button onClick={this.onUpdateClient.bind(this)}&gt;。每次渲染此组件时,这将生成一个新的函数引用。将其绑定在构造函数上或使用转译器。 -- 你可能会想“但它只是一个小功能”......但是当你养成习惯并最终进入一个包含数百个组件的页面时,它会加起来(并吃掉你的记忆并减慢你的应用程序)。跨度>
  • @SergioMoura 感谢您的建议,但我已经在回答中包含了这些信息
  • 对此感到抱歉。我只是后来才读到它......每次看到它都让我感到厌烦。我使用包含大约 1200 个组件的代码库......事情会变得很快!此外,您将onclickonClick 钉在了一起。
  • 哈哈,没错。谈到最佳实践,我也有同感@SergioMoura
  • 谢谢你们给我这么好的建议。我只有几天的反应时间,所以所有这些都非常有帮助。
猜你喜欢
  • 2017-08-22
  • 2018-04-09
  • 1970-01-01
  • 2023-03-18
  • 2021-01-27
  • 1970-01-01
  • 1970-01-01
  • 2021-10-05
  • 1970-01-01
相关资源
最近更新 更多