【问题标题】:ReactJS Component function call this and props undefinedReactJS 组件函数调用 this 和 props 未定义
【发布时间】:2016-10-15 13:38:28
【问题描述】:

这可能是一个简单的 React 问题,但我是新手。在完成了一些教程和优秀的在线课程之后,我正在尝试我的第一个合适的 ReactJS 项目。我也咬过 ES6 和 JSX,所以这可能是问题所在。基本上,使用作为props传入的数组,然后调用子函数对数据结构进行登录我想传入要调用onClick的函数作为props,但是“this”在函数中是未定义的,虽然它是正在传递给 array.map 函数...

import React from 'react';
import { Link, Location } from 'react-router';

import moment from 'moment';
import _ from 'lodash';

import IBoxTools from '../common/iboxTools';

class Timesheets extends React.Component {

    componentDidMount() {
        $('.timesheets li button').tooltip();
    }

    render() {

        const showTimesheets = function (timesheets) {

            if (timesheets && timesheets.length) {
                return (
                    <div>
                        <ul className="list-group timesheets">
                            {timesheets.map(timesheetCandidateRow, this)}
                        </ul>
                        <Link to="/timesheets" className="btn btn-primary">View all timesheets</Link>
                    </div>
                );
            }
            else {
                return (
                    <div>
                        <p>There are currently no timesheets requiring action</p>
                        <a className="btn btn-primary" href="#">View all timesheets</a>
                    </div>);
            }
        }

        const timesheetCandidateRow = function (timesheetCandidate) {
            var candidateName = timesheetCandidate.candidate.forename + ' ' + timesheetCandidate.candidate.surname;
            return (
                <li className="list-group-item" key={timesheetCandidate.id}>
                    <div>
                        <h4 className="list-group-item-heading">{candidateName}<br /><small>{timesheetCandidate.candidate.title}</small></h4>
                        <table className="table table-condensed">
                            <tbody>
                                {timesheetCandidate.timesheets.map(timesheetRow, this)}
                            </tbody>
                        </table>
                    </div>
                </li>
            );
        }

        const timesheetRow = function (timesheet) {
            var timesheetDate = moment(timesheet.date).format('dddd Do MMM');
            if (timesheet.startTime) {
                timesheetDate = timesheetDate + ' ' + timesheet.startTime + ' to ' + timesheet.endTime;
            }
            return (
                <tr key={timesheet.id}>
                    <td>{timesheetDate}</td>
                    <td>{timesheet.charge}</td>
                    <td style={{ width: 70 }}>
                        <div className="btn-group">
                            <button className="btn btn-success btn-xs" onClick={this.props.onAccept} title="Accept" data-toggle="tooltip" data-placement="bottom"><i className="fa fa-check"></i></button>
                            <button className="btn btn-danger btn-xs" onClick={this.props.onReject} title="Reject" data-toggle="tooltip" data-placement="bottom"><i className="fa fa-close"></i></button>
                        </div>
                    </td>
                </tr>
            );
        }

        return (
            <div className="ibox float-e-margins">
                <div className="ibox-title">
                    <h5>
                        <span className="fa-stack">
                            <i className="fa fa-square-o fa-stack-2x"></i>
                            <i className="fa fa-check fa-stack-1x"></i>
                        </span> Timesheets
                                </h5>
                    <IBoxTools />
                </div>
                <div className="ibox-content">
                    {showTimesheets(this.props.timesheets)}
                </div>
            </div>
        );
    }

}

Timesheets.propTypes = {
    timesheets: React.PropTypes.array,
    onAccept: React.PropTypes.func.isRequired,
    onReject: React.PropTypes.func.isRequired
}

export default Timesheets;

因此,在 render 方法的 const 中,“this”是未定义的。有什么帮助吗?

谢谢。

【问题讨论】:

    标签: reactjs ecmascript-6


    【解决方案1】:

    要“锁定”this,您可以使用箭头函数

     const showTimesheets =  (timesheets) => {...}
    

    timesheetCandidateRow 和任何其他内部函数也是如此。

    您也可以使用 Vlad 发布的绑定解决方案,但这要求您确保调用您的函数并传递正确的 this(使用绑定、调用或应用)

    【讨论】:

    • 抱歉,回答得太早了,我更喜欢下面的 .bind。谢谢。
    【解决方案2】:

    不要将 this 作为普通参数传递,而是尝试在上下文切换的所有 3 个位置将您的函数绑定到正确的调用对象:

    timesheets.map(timesheetCandidateRow.bind(this))
    
    timesheetCandidate.timesheets.map(timesheetRow.bind(this))
    
    showTimesheets.bind(this)(this.props.timesheets)
    

    https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Function/bind

    【讨论】:

    • 使用箭头函数不需要你改变所有的调用者
    • 这很酷,不知道箭头函数隐式绑定到调用者的 this。下次试试。
    • 不是来电者的这个。这是外部函数的词法 this 。就像您将const me =this 添加到外部函数并在内部函数中使用 me 而不是 this 一样
    猜你喜欢
    • 2015-07-20
    • 1970-01-01
    • 1970-01-01
    • 2020-08-26
    • 2016-11-09
    • 2020-06-13
    • 2020-05-05
    相关资源
    最近更新 更多