⚠️ Почему вы получаете эту ошибку
Вы получаете эту ошибку, потому что вместо того, чтобы просто вызывать 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/