问题 ReactJS:当子组件调用parent时,“this.props”不是函数


我已编写此代码,目前正在与onClick事件中的错误争论。我有两个事件,子元素上的onClick事件和顶级父元素上的onChange事件。

预期的行为应该是更改当前在Container组件中保存的activeAccount变量。为此,我在AccountRow组件上添加了一个onClick处理程序,然后应该调用顶级父级的onChange函数。

但是,行

'this.props.onChange(this.props.account)',

handleClick: function(e) {
        this.props.onChange(this.props.account);
    },    

意味着使用参数'this.props.account'调用父函数,

给我这个错误:

Uncaught TypeError: this.props.onChange is not a function.

我最初认为这是一个范围问题,但我补充说

{...this.props}

在父容器中的每个子项和嵌套子项上 零件。因此,所有道具都应该传播到AccountRow组件。然而,问题仍然存在。

    var ACCOUNTS = [
    {name: 'cash on hand'},
    {name: 'savings account'},
    {name: 'shared account'},
    {name: 'my second wallet'}
];

var TRANSACTIONS = [
    {date: '', name: 'Bananas', amount: 6, category: 'Groceries', account: 'cash on hand'},
    {date: '', name: 'Apples', amount: 2.50, category: 'Groceries', account: 'cash on hand'},
    {date: '', name: 'Cash withdrawal', amount: 250, account: 'savings account'}
];

var AccountRow = React.createClass({

    handleClick: function(e) {
        this.props.onChange(this.props.account);
    },

    render: function () {
        return (
            <li onClick = {this.handleClick}> {this.props.account}</li>
        )}
});

var AccountList = React.createClass({

    render: function () {

        var rows = [];
        this.props.accounts.map(function(each_account) {
            rows.push(
                <AccountRow 
                    account = {each_account.name} 
                    key = {each_account.name}
                    {...this.props}     
                />);
                      })
    return (
        <ul>
        {rows}
        </ul>
    )   
    }   
});


var NavBar = React.createClass({

    render: function () {
        return (
            <div id = 'account-tabs'>
                <h2> Accounts </h2>
                <AccountList 
                    accounts = {this.props.accounts} 
                    {...this.props} 
                />
            </div>
        )
    }
});

var TransactionRow = React.createClass({
    render: function (){
        var trans = this.props.transaction;

        return (
            <tr>
            <td>{trans.date}</td>
            <td>{trans.name}</td>
            <td>{trans.amount}</td>
            <td>{trans.account}</td>
            <td><a href = ''>edit</a></td>
            </tr>
        )
    }
});

var TransactionList = React.createClass ({                      
    render: function () {

        var activeaccount = this.props.activeAccount;

        var rows = [];
        this.props.transactions.map(function(each_transaction) {
            if (each_transaction.account == activeaccount) {

                /* Very strange behaviour
                if (each_transaction account == this.props.activeAccount) 
                DOES NOT WORK, I do not know why this is the case
                */

                rows.push(<TransactionRow transaction = {each_transaction} key = {each_transaction.name} />);
            }
            else {
                /*console.log(each_transaction.account);*/
            }     
        })
        return (
            <tbody>
            {rows}
            </tbody>
        )
    }
});

var TransactionsTable = React.createClass({
    render: function() {

        return (
            <div id = 'recent-transactions'>
            <h2>Recent Transactions for {this.props.activeAccount}</h2>
            <table>
                <tr>
                    <th>date</th>
                    <th>name</th>
                    <th>amount</th>
                    <th>account</th>
                    <th>edit </th>
                </tr>
                <TransactionList 
                    transactions = {this.props.transactions}
                    activeAccount = {this.props.activeAccount}
            />
            </table>
            </div>
        )
    }
});

var TransactionForm = React.createClass({
    render: function() {
        return (
            <div>
            <h2>Add Transaction </h2>
            <p>Transaction name</p>
            <input type = 'text' />
            <p>Price</p>
            <input type = 'number'/>
            <p>Category (optional) </p>
            <input type = 'text' />
            </div>
        )
    }
});


var ButtonMenu = React.createClass ({
    render: function () {
        return (
            <div>
            <button>Add Transaction</button>
            </div>
        )
    }
});

var Container = React.createClass({

    getInitialState: function (){
        return {
            activeAccount: ACCOUNTS[0].name
        };
    },

    setActiveAccount: function(dat) {
        this.setState({
            activeAccount: dat  
        });
    },

    render: function () {
        return (
            <div id = 'wrapper'>
            <NavBar 
                accounts = {ACCOUNTS}
                activeAccount = {this.state.activeAccount}
                onChange = {this.setActiveAccount}
                {...this.props}
            />
            <TransactionsTable 
                transactions = {TRANSACTIONS}
                activeAccount = {this.state.activeAccount}
            />
            <TransactionForm />
            <ButtonMenu />
            </div>
        );
    }
});


React.render(<Container />, document.body);

感谢您的时间。


8198
2018-05-01 08:37


起源

你确定 this.props 实际上有一个 onChange 回调函数? - skyline75489
我相信我在Container的render函数下的<NavBar>组件中有它。 - Lieu Zheng Hong


答案:


问题是由 map 功能,你应该传入 this 对于 thisArg 打电话的时候 map

this.props.accounts.map(function(each_account) {
  rows.push(
    <AccountRow 
      account = {each_account.name} 
      key = {each_account.name}
      {...this.props}     
    />);
 }, this);

但是,这会导致 AccountRow 有冗余变量 accounts 和 activeAccount。我认为你应该考虑只转移 onChange 功能:

 <AccountRow 
     account = {each_account.name} 
     key = {each_account.name}
     onChange = {this.props.onChange}
 />

9
2018-05-01 10:07



接得好!我怎么通过 onChange 功能下来链?我是否创建了一个新功能 <AccountRow onChange2 = {function} />);    然后调用顶级 onChange 功能?或者有没有办法通过 onChange 方法通过道具? - Lieu Zheng Hong
我编辑了答案。希望能帮助到你。 - skyline75489
感谢您的帮助!你能解释一下吗? , this 附在最后 rows.push 功能有助于解决这个问题吗? - Lieu Zheng Hong
map 被定义为 arr.map(callback[, thisArg])。如果你不通过 thisArgs,它会用 undefined 如 this 在回调块和 this.props 会不正确的。 - skyline75489