调用内部的箭头函数反应渲染

时间:2018-05-06 03:24:23

标签: reactjs

我想在map函数中调用函数里面的render render方法。我的示例代码:

module.exports = {
  // ...
  resolve: {
    alias: {
      'vue$': 'vue/dist/vue.esm.js' // 'vue/dist/vue.common.js' for webpack 1
    }
  }
}

并调用this.balance()

render() {
 return (
 {this.state.studentLedger.map((post, i) => (                                                                            
    <tr key={i}>                                                                                
      <td>{ i+1 }</td>                                                                                    
      <td>{ post.transaction_date }</td>                                                                                       
      <td>{ post.particular }</td>                                                                                
      <td>{ post.dr }</td>                                                                                         
      <td>{ post.cr }</td>                                                                                        
      <td>{(post) => this.balance(post.dr, post.cr)} { this.state.balance }</td>                                                                                
    </tr>
 ))}
 )}

我得到了balance(dr, cr){ this.state.balance ? this.setState({balance : (this.state.balance + dr)}) : this.setState({balance : (this.state.balance - cr)}); } 。我怎样才能实现这个功能。

2 个答案:

答案 0 :(得分:3)

⚠️为什么会收到该错误

您收到该错误的原因是,您不是仅调用this.balance并使用{}评估其返回值(可能输出string),而是创建新的箭头函数,你不是在打电话,而是评估它。

这一行:

<td>{ (post) => this.balance(post.dr, post.cr) } { this.state.balance }</td>

应该是:

<td>{ this.balance(post.dr, post.cr) } { this.state.balance }</td>

假设this.balance只是一个函数,它返回您想要在组件中显示的文本,但情况并非如此,因为您没有从中返回任何内容。< / p>

☢️你不应该做什么

更糟糕的是,您不应该从setState致电renderrender不应导致任何副作用,在您的情况下,调用setState会触发重新渲染,再次调用setState,这将... ...基本上,您将结束无限循环。

️如何修复它

我想您只想显示余额随时间的变化,因此为此,您不需要更新状态。您可以保持原样,只保留当前余额和Array个交易。然后,当您在render内循环浏览它们时,您将更新本地 balance变量,该变量将显示在每一行上,如下所示:

&#13;
&#13;
class Balance extends React.Component {
  constructor(props) {
    super(props);
    
    this.state = { balance: 2000, studentLedger: [{
        transaction_date: '5 MAY 2018',
        dr: 1200,
        cr: 0,
      }, {
        transaction_date: '1 MAY 2018',
        dr: 0,
        cr: 100,
      }, {
        transaction_date: '20 APR 2018',
        dr: 0,
        cr: 100,
      }, {
        transaction_date: '10 APR 2018',
        dr: 800,
        cr: 0,
      }, {
        transaction_date: '1 APR 2018',
        dr: 0,
        cr: 600,
      }, {
        transaction_date: '22 MAR 2018',
        dr: 0,
        cr: 200,
      }, {
        transaction_date: '1 MAR 2018',
        dr: 1000,
        cr: 0,
      }, {
        transaction_date: '1 JAN 2018',
        dr: 0,
        cr: 0,
      }],
    };
  }
  
  render() {      
    const studentLedger = this.state.studentLedger;
    const totalEntries = studentLedger.length;
  
    // Balance is the current amount:
    let balance = this.state.balance;
  
    const rows = studentLedger.map((post, i) => {
      
      // We start displaying the current amount:
      const currentBalance = balance;
      
      // And we update it for the next iteration (note the signs are the opposite of
      // what you might think at first):
      balance += -post.dr || post.cr;
      
      return (
        <tr key={ i }>
          <td>{ totalEntries - i }</td>
          <td>{ post.transaction_date }</td>
          <td>{ post.dr }</td>
          <td>{ post.cr }</td>
          <td>{ currentBalance }</td>
        </tr>
      );
    });

    return (
      <table>
        <tr>
          <th>ID</th>
          <th>DATE</th>
          <th>DR</th>
          <th>CR</th>
          <th>BALANCE</th>
        </tr>

        { rows }

      </table>
    );
  }
}

ReactDOM.render(<Balance />, document.getElementById('app'));
&#13;
body {
  font-family: monospace;
}

table {
  border: 2px solid #000;
  border-collapse: collapse;
  text-align: right;
  width: 100%;
}

th,
td {
  border: 2px solid #000;
  padding: 8px 16px;
  width: 20%;
}

th {
  background: #000;
  color: #FFF;
}
&#13;
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react-dom.min.js"></script>

<div id="app"></div>
&#13;
&#13;
&#13;

如果您愿意,还可以更新constructor中的状态,以便每个条目都包含计算的余额。如果您使用的是Redux,您可能希望在reducer中执行此操作,或者您甚至可以考虑使用Reselect和选择器:http://blog.rangle.io/react-and-redux-performance-with-reselect/

答案 1 :(得分:1)

使用此代码以正确的方式显示学生平衡,而不通过在渲染中调用setstate进入无限循环。

除此之外,你需要做的是你必须写balance(i, dr,cr){...},它会返回第i个学生的正确平衡。并在设置state.studentLedger的值时立即调用setStudentBalance()。

setStudentBalance(){
    let balances = this.state.studentLedger.map((post, i) =>{
        return this.balance(i, post.dr, post.cr)
    })
    this.setState({studentBalances:balances})
}

render() {
     return (
     {this.state.studentLedger.map((post, i) =>(                                                                            
        <tr key={i}>                                                                                
          <td>{ i+1 }</td>                                                                                    
          <td>{ post.transaction_date }</td>                                                                                       
          <td>{ post.particular }</td>                                                                                
          <td>{ post.dr }</td>                                                                                         
          <td>{ post.cr }</td>                                                                                        
          <td>{this.state.balance[i] }</td>                                                                                
        </tr>
       )
      )}
     )}