[英]Change in state propagation to props stops at react-redux-connected component
I have the following hierarchy of components: 我具有以下组件层次结构:
The state is kept in MyPayments component (it is local state - even though you can see connected components, I barely use Redux). 状态保存在MyPayments组件中(它是本地状态-即使您可以看到连接的组件,我也很少使用Redux)。
It has the following structure: 它具有以下结构:
{
payments: [
{
amount: 400.00,
status: pending
//...
},
{
amount: 200.00,
status: approved
//...
}
]
}
The payments
array is passed to the child component (connected ClientPayments
) as a prop - you can see it on the screenshot above. payments
数组作为道具传递给子组件(连接的ClientPayments
)-您可以在上面的屏幕截图中看到它。 I believe that the connected component passes it further down to the ClientPayments
component. 我相信连接的组件将其进一步传递给
ClientPayments
组件。 But... 但...
At some point in time, after a successful AJAX request, the status property of one of the payments may change. 在某个时间点,成功的AJAX请求后,其中一项付款的状态属性可能会更改。 When it does, I want to change how the payment is rendered inside the
ClientPayments
component. 这样做时,我想更改如何在
ClientPayments
组件内呈现付款。 However, when I inspect the props of the ClientPayments
component in React devtools, I can see that the changed payment still has the same status here. 但是,当我检查React devtools中
ClientPayments
组件的道具时,我可以看到更改后的付款在这里仍然具有相同的状态。 The Connect(ClientPayments)
component though has its payments prop correctly updated. 尽管
Connect(ClientPayments)
组件的付款Connect(ClientPayments)
正确更新。
MyPayments.js MyPayments.js
import React, { Component } from 'react'
import { connect } from 'react-redux'
import { camelCaseKeysDeep } from './Utils'
import ClientPayments from './ClientPayments'
class MyPayments extends Component {
constructor () {
super()
this.state = {
payments: [],
isLoading: false,
}
this.updatePaymentStatus = this.updatePaymentStatus.bind(this)
}
componentDidMount () {
this.setState({
isLoading: true,
})
axios.get(`/api/users/${this.props.userId}/payments`, {
params: {
includes: [
'bankAccount',
],
},
}).then(response => {
const payments = response.data
const camelCasedPayments = camelCaseKeysDeep(payments)
this.setState({
payments: camelCasedPayments,
isLoading: false,
})
}).catch((thrown) => {
console.log(thrown)
this.setState({
isLoading: false,
})
})
}
updatePaymentStatus(paymentId, newStatus) {
this.setState((prevState) => {
let payments = prevState.payments
const paymentIndex = _.findIndex(payments, (payment) => (payment.id === paymentId))
payments[paymentIndex].status = newStatus
return {
payments: payments
}
})
}
render () {
const {payments, isLoading} = this.state
const userId = this.props.userId
const expandedId = parseInt(this.props.match.params.id)
return (
<div>
<h2>My payments</h2>
<div className='panel panel-default'>
<ClientPayments payments={payments} isLoading={isLoading}
expandedId={expandedId} userId={userId} onPaymentStatusChange={this.updatePaymentStatus}/>
</div>
</div>
)
}
}
const mapStateToProps = state => {
return {
userId: state.user.id,
}
}
export default connect(mapStateToProps)(MyPayments)
ClientPayments.js ClientPayments.js
import React, { Component } from 'react'
import { Button, Table } from 'react-bootstrap'
import { LinkContainer } from 'react-router-bootstrap'
import { connect } from 'react-redux'
import Loader from './Loader'
import PaymentRow from './PaymentRow'
import withFileUpload from './withFileUpload'
import SingleUploader from './SingleUploader'
import BankAccountTable from './BankAccountTable'
import StatusIndicator from './StatusIndicator'
import PaymentStatusAlert from './PaymentStatusAlert'
class ClientPayments extends Component {
constructor (props) {
super(props)
this.SingleUploaderWithFU = withFileUpload(
SingleUploader,
'file',
)
this.handleSwiftCopyUploaded = this.handleSwiftCopyUploaded.bind(this)
}
handleSwiftCopyUploaded (paymentId) {
this.props.dispatch({
type: 'NOTIFY',
status: 'success',
message: 'A new SWIFT copy has been uploaded',
})
axios.put(`/api/payments/${paymentId}/status`, {
'status': 'pending',
}).then(() => {
this.props.onPaymentStatusChange(paymentId, 'pending')
})
}
render () {
const {payments, isLoading, expandedId} = this.props
return (
<Table responsive striped hover fill>
<thead>
<tr>
<th />
<th>Created</th>
<th>Amount</th>
<th>Bank</th>
<th>Actions</th>
</tr>
</thead>
{
payments.map((payment) => {
const storedSwiftCopy = payment.swiftCopyNameOrig !== null ? {
name: payment.swiftCopyNameOrig,
preview: payment.swiftCopyFullPath,
thumb: payment.swiftCopyThumbPath,
} : null
return (
<PaymentRow key={payment.id} payment={payment}
initiallyExpanded={expandedId === payment.id}>
<div>
<StatusIndicator status={payment.status}/>
<PaymentStatusAlert status={payment.status} rejectionMsg={payment.rejectionMsg}/>
<h4>Bank account details</h4>
<BankAccountTable bankAccount={payment.bankAccount}/>
<h4>Swift copy upload</h4>
<this.SingleUploaderWithFU initFile={storedSwiftCopy}
autoUpload
postUrl={`/api/payments/${payment.id}/swift-copy`}
onFileUploaded={() => this.handleSwiftCopyUploaded(payment.id)}/>
</div>
</PaymentRow>
)
})
}
{
isLoading ? (
<tbody>
<tr>
<td colSpan={5}>
<div className='vertical-spacer'>
<Loader />
</div>
</td>
</tr>
</tbody>
) : (
payments.length === 0 && (
<tbody>
<tr>
<td colSpan={5}>
<div className='vertical-spacer'>
<div>
<p className='text-center'>You have no payments yet.</p>
<p className='text-center'>
<LinkContainer to='/payments/new'>
<Button bsStyle='primary'>Receive one</Button>
</LinkContainer>
</p>
</div>
</div>
</td>
</tr>
</tbody>
)
)
}
</Table>
)
}
}
export default connect()(ClientPayments)
Why isn't the state change propagated? 为什么状态更改没有传播? What can I do to fix it?
我该如何解决?
You can find some related topic here: React: why child component doesn't update when prop changes 您可以在此处找到一些相关主题: React:为什么在prop更改时子组件不会更新
Also, please try to print the data you get on componentShouldUpdate, you can find it here: https://facebook.github.io/react/docs/react-component.html#shouldcomponentupdate 另外,请尝试打印在componentShouldUpdate上获得的数据,您可以在这里找到它: https : //facebook.github.io/react/docs/react-component.html#shouldcomponentupdate
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.