Вызов функции стрелки внутри реагирующего рендера - PullRequest
0 голосов
/ 06 мая 2018

Я хочу вызвать функцию в методе render render в функции map. Мой пример кода:

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>
 ))}
 )}

И вызов this.balance ()

balance(dr, cr){
    this.state.balance ? this.setState({balance : (this.state.balance + dr)}) : this.setState({balance : (this.state.balance - cr)});
}

Я получил Warning: Functions are not valid as a React child.. Как я могу достичь этой функции.

Ответы [ 2 ]

0 голосов
/ 06 мая 2018

Используйте этот код для правильного отображения баланса учеников, не заходя в бесконечные циклы, вызывая setstate внутри render.

В дополнение к этому вам необходимо написать balance(i, dr,cr){...}, который возвращает правильный баланс i-го студента. И вызовите setStudentBalance (), как только вы установите значение для state.studentLedger.

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>
       )
      )}
     )}
0 голосов
/ 06 мая 2018

⚠️ Почему вы получаете эту ошибку

Вы получаете эту ошибку, потому что вместо того, чтобы просто вызывать 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 - это просто функция, которая возвращает текст, который вы хотите отобразить в вашем компоненте, но это не так, поскольку вы ничего не возвращаете из него.

☢️ Чего не следует делать

Что еще хуже, вам не следует звонить setState с render. render не должен вызывать никаких побочных эффектов, и в вашем случае вызов setState вызовет повторный рендеринг, который снова вызовет setState, что ... По сути, вы получите бесконечный цикл .

?️ Как это исправить

Полагаю, вы просто хотите отобразить изменения баланса с течением времени, поэтому для этого вам не нужно обновлять состояние. Вы можете оставить все как есть, используя только текущий баланс и Array транзакций. Затем, перебирая их внутри render, вы обновляете локальную balance переменную, которая будет отображаться в каждой строке, например:

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'));
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;
}
<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>

При желании вы также можете обновить состояние в constructor, чтобы каждая запись уже содержала рассчитанный баланс. Если вы используете Redux, вы можете сделать это в своем редукторе, или вы даже можете рассмотреть возможность использования Reselect и селектора: http://blog.rangle.io/react-and-redux-performance-with-reselect/

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...