Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/javascript/395.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Javascript 状态传播到道具的更改在react redux连接的组件处停止_Javascript_Reactjs_React Redux - Fatal编程技术网

Javascript 状态传播到道具的更改在react redux连接的组件处停止

Javascript 状态传播到道具的更改在react redux连接的组件处停止,javascript,reactjs,react-redux,Javascript,Reactjs,React Redux,我有以下组件层次结构: 状态保存在MyPayments组件中(它是本地状态-尽管您可以看到连接的组件,但我几乎不使用Redux) 其结构如下: { payments: [ { amount: 400.00, status: pending //... }, { amount: 200.00, status: approved //... } ] } payments数组作为道具传递

我有以下组件层次结构:

状态保存在MyPayments组件中(它是本地状态-尽管您可以看到连接的组件,但我几乎不使用Redux)

其结构如下:

{
  payments: [
    {
      amount: 400.00,
      status: pending
      //...
    },
    {
      amount: 200.00,
      status: approved
      //...
    }
  ]
}
payments
数组作为道具传递给子组件(已连接的
ClientPayments
),您可以在上面的屏幕截图上看到它。我相信连接的组件会将其进一步传递给
ClientPayments
组件。但是

在某个时间点,在成功的AJAX请求之后,其中一个付款的status属性可能会更改。当它出现时,我想更改
ClientPayments
组件中付款的呈现方式。但是,当我在React devtools中检查
ClientPayments
组件的道具时,我可以看到更改的付款在这里仍然具有相同的状态。
Connect(ClientPayments)
组件的payments属性已正确更新

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)
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)
import React,{Component}来自“React”
从“react redux”导入{connect}
从“/Utils”导入{camelCaseKeysDeep}
从“/ClientPayments”导入ClientPayments
类MyPayments扩展组件{
构造函数(){
超级()
此.state={
付款:[],
孤岛加载:false,
}
this.updatePaymentStatus=this.updatePaymentStatus.bind(this)
}
组件安装(){
这是我的国家({
孤岛加载:是的,
})
get(`/api/users/${this.props.userId}/payments`{
参数:{
包括:[
“银行账户”,
],
},
})。然后(响应=>{
const payments=response.data
const camelCasedPayments=camelCaseKeysDeep(付款)
这是我的国家({
付款:CAMELDCASED付款,
孤岛加载:false,
})
}).catch((抛出)=>{
console.log(抛出)
这是我的国家({
孤岛加载:false,
})
})
}
updatePaymentStatus(paymentId,newStatus){
this.setState((prevState)=>{
let payments=prevState.payments
const paymentIndex=..findIndex(付款,(付款)=>(payment.id==paymentId))
付款[paymentIndex]。状态=新闻状态
返回{
付款:付款
}
})
}
渲染(){
const{payments,isLoading}=this.state
const userId=this.props.userId
const expandedId=parseInt(this.props.match.params.id)
返回(
我的付款
)
}
}
常量mapStateToProps=状态=>{
返回{
userId:state.user.id,
}
}
导出默认连接(MapStateTops)(MyPayments)
ClientPayments.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)
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)
import React,{Component}来自“React”
从“react bootstrap”导入{按钮,表}
从“react router bootstrap”导入{LinkContainer}
从“react redux”导入{connect}
从“./Loader”导入加载程序
从“/PaymentRow”导入PaymentRow
从“/withFileUpload”导入withFileUpload
从“./SingleUploader”导入SingleUploader
从“/BankAccountTable”导入BankAccountTable
从“./StatusIndicator”导入StatusIndicator
从“/PaymentStatusAlert”导入PaymentStatusAlert
类ClientPayments扩展组件{
建造师(道具){
超级(道具)
this.SingleUploaderWithFU=withFileUpload(
单一上传程序,
“文件”,
)
this.handleswitcopyUpload=this.handleswitcopyUpload.bind(this)
}
HandleSwiftCopyUpload(paymentId){
这是我的道具({
键入:“通知”,
状态:“成功”,
消息:“新的SWIFT副本已上载”,
})
axios.put(`/api/payments/${paymentId}/status`{
“状态”:“挂起”,
}).然后(()=>{
this.props.onPaymentStatusChange(paymentId为'pending')
})
}
渲染(){
const{payments,isLoading,expandedId}=this.props
返回(
创建
数量
银行
行动
{
payments.map((付款)=>{
const storedSwiftCopy=payment.swiftCopyNameOrig!==null{
名称:payment.swiftCopyNameOrig,
预览:payment.swiftCopyFullPath,
thumb:payment.swiftCopyThumbPath,
}:null
返回(
银行帐户详细信息
快速拷贝上传
this.handleswitcopyUpload(payment.id)}/>
)
})
}
{
孤岛(
) : (
payments.length==0&&(

您还没有付款

接一个

) ) } ) } } 导出默认连接()(ClientPayments)

为什么不传播状态更改?我能做些什么来修复它?

您可以在这里找到一些相关主题:

而且, 请尝试打印您在componentShouldUpdate上获得的数据, 你可以在这里找到它: