如何呈现共享组件

时间:2018-01-23 14:30:15

标签: javascript reactjs

我正在尝试解决使用共享组件时遇到的问题。我的父组件看起来像这样..

index.js

import AuditData from './components/audit-data'
import StoredData from './components/stored-data'

class Audits extends PureComponent {
  render = () => {
    const {metroAudit} = this.props
    const isMonthly = metroAudit.get('isMonthly')

    return (
      <Card className='animated fadeIn'>
        <CardBody>
              <Row>
                <Col>
                  <h5 className='text-center'>Stored Data</h5>
                  <Card>
                    <CardBody><StoredData /></CardBody>
                  </Card>
                </Col>
                <Col>
                  <h5 className='text-center'>Audit Data</h5>
                  <Card>
                    <CardBody><AuditData /></CardBody>
                  </Card>
                </Col>
              </Row>
            </div>}
        </CardBody>
      </Card>
    )
  }
}

除了他们使用的数据外,StoredData和AuditData是相同的。这两个组件都是这样的..

import React, { PureComponent } from 'react'
import PropTypes from 'prop-types'
import Immutable from 'immutable'
import cloneDeep from 'lodash/cloneDeep'
import { Row, Col } from 'reactstrap'
import { connect } from 'react-redux'
import Amenities from '../common/amenities'
import OwnershipType from '../common/ownership-type'

const initState = {
  noAmenities: false,
  feeSimple: true,
  checkboxes: [{
    label: '',
    value: '',
    checked: false
  }]
}

class StoredData extends PureComponent {
  static propTypes = {
    series: PropTypes.instanceOf(Immutable.Map),
    markets: PropTypes.instanceOf(Immutable.Map),
    sbd: PropTypes.instanceOf(Immutable.Map)
  }

  constructor (props) {
    super(props)
    this.state = initState
  }

  componentDidUpdate = prevProps => {
    const { markets } = this.props
    const prevMarket = prevProps.markets.get('market')
    const market = markets.get('market')

    if (market !== prevMarket) this.setState(initState)
  }

  componentDidMount = () => {
    this._setData()
  }

  _setData = () => {
    const { sbd } = this.props
    const _checkboxes = sbd.get('amenities').toJS()
    const _amenities = sbd.getIn(['data', 'amenities']).toJS()
    _checkboxes.shift()
    _checkboxes.forEach(x => {
      x.isDisabled = true
      x.checked = !!_amenities.find(y => y.value === x.value)
    })
    this.setState({checkboxes: _checkboxes})
  }

  _onOwnershipType = e => {
    const val = e.target.value
    const _state = cloneDeep(this.state)
    _state.feeSimple = val !== 'condoOwnership'
    this.setState(_state)
  }

  _onNoAmenities = () => {
    const { checkboxes } = this.state
    const _checkboxes = cloneDeep(checkboxes)
    _checkboxes.forEach(x => {
      x.checked = false
    })
    this.setState({ noAmenities: !this.state.noAmenities, checkboxes: _checkboxes })
  }

  _onAmenities = (e, i) => {
    const { checkboxes } = this.state
    const _checkboxes = cloneDeep(checkboxes)
    _checkboxes[i].checked = !_checkboxes[i].checked
    this.setState({checkboxes: _checkboxes})
  }

  render = () => {
    return (
      <div>
        <Row>
          <Col>
            <OwnershipType
              isStoredData
              onOwnershipType={this._onOwnershipType}
              {...this.state}
            />
          </Col>
        </Row>
        <Row>
          <Col>
            <Amenities
              onNoAmenities={this._onNoAmenities}
              onCheckboxes={this._onAmenities}
              {...this.state}
            />
          </Col>
        </Row>
      </div>
    )
  }
}

const mapStateToProps = state => ({
  series: state.series,
  markets: state.markets,
  sbd: state.sbd
})

export default connect(mapStateToProps)(StoredData)

这两个组件也是共享的。

import Amenities from '../common/amenities'
import OwnershipType from '../common/ownership-type'

ownershipType.js

import React, {PureComponent} from 'react'
import PropTypes from 'prop-types'
import { CardBody, Card, Row, Col } from 'reactstrap'
import CardTitle from '../../../../../../../components/CardTitle'
import Radios from '../../../../../../../components/Radios/index'

export default class OwnershipType extends PureComponent {
  static propTypes = {
    feeSimple: PropTypes.bool,
    isStoredData: PropTypes.bool,
    onOwnershipType: PropTypes.func
  }

  render = () => {
    const {feeSimple, isStoredData, onOwnershipType} = this.props
    return (
      <Card className='animated fadeIn'>
        <CardTitle
          color='default'
          h6Class='card-h6-sbd'
          className='card-title-sbd'
          title='Ownership Type' />
        <CardBody>
          <Row>
            <Col>
              <Radios
                name={`${isStoredData ? 'ownershipType' : 'ownershipType-1'}`}
                label1='Fee Simple'
                label2='Condo Ownership'
                value1={'feeSimple'}
                value2={'condoOwnership'}
                checked1={feeSimple}
                checked2={!feeSimple}
                onChange={onOwnershipType}
              />
            </Col>
          </Row>
        </CardBody>
      </Card>
    )
  }
}

amenities.js

import React, {PureComponent} from 'react'
import PropTypes from 'prop-types'
import uuid from 'uuid'
import { CardBody, Card, Row, Col } from 'reactstrap'
import CardTitle from '../../../../../../../components/CardTitle'
import Checkbox from '../../../../../../../components/Checkbox/index'

export default class Amenities extends PureComponent {
  static propTypes = {
    noAmenities: PropTypes.bool,
    onNoAmenities: PropTypes.func,
    onCheckboxes: PropTypes.func,
    checkboxes: PropTypes.array
  }

  render = () => {
    const {noAmenities, onNoAmenities, checkboxes, onCheckboxes} = this.props

    return (
      <Card className='animated fadeIn'>
        <CardTitle
          color='default'
          h6Class='card-h6-sbd'
          className='card-title-sbd'
          title='Amenities' />
        <CardBody>
          <Row>
            <Col>
              <Checkbox
                name='noAmenities'
                value='noAmenities'
                label='No Amenities'
                divClass='pull-right'
                checked={noAmenities}
                onChange={onNoAmenities}
              />
            </Col>
          </Row>
          <Row>
            {checkboxes.map((item, i) => (
              <Col key={i} sm={6} md={6} lg={6}>
                <Checkbox
                  name={uuid.v4()}
                  disabled={item.isDisabled}
                  value={item.value}
                  label={item.label}
                  checked={item.checked}
                  onChange={e => onCheckboxes(e, i)}
                />
              </Col>
            ))}
          </Row>
        </CardBody>
      </Card>
    )
  }
}

问题是我设置数据的时候。当我同时“StoredData”和“AuditData”呈现时,StoredData复选框未正确设置。如果比较“_setData”函数,您将看到StoredData具有动态数据,用于确定是否选中了每个复选框。但是,两个组件都通过AuditData设置复选框  “_setData”函数。共享具有相同父组件的组件时是否存在参考问题?我之前没有遇到过这个问题,也不知道要搜索什么。

1 个答案:

答案 0 :(得分:0)

import React, { PureComponent } from 'react'
import { Row, Col, Card, CardBody } from 'reactstrap'
import PropTypes from 'prop-types'
import ReactTimeout from 'react-timeout'
import AuditData from './components/audit-data'
import StoredData from './components/stored-data'

class MetroAuditMain extends PureComponent {
  static propTypes = {
    setTimeout: PropTypes.func
  }

  constructor (props) {
    super(props)
    this.state = {hidden: true}
  }

  componentWillMount = () => {
    this.props.setTimeout(() => this.setState({hidden: false}), 500)
  }

  render = () => {
    const {hidden} = this.state
    return (
      <Row className='animated fadeIn'>
        <Col xs={12} sm={12} md={12} lg={6} xl={6}>
          <Card>
            <CardBody>
              <StoredData />
            </CardBody>
          </Card>
        </Col>
        <Col xs={12} sm={12} md={12} lg={6} xl={6}>
          <Card>
            <CardBody>
              {!hidden && (
                <AuditData />
              )}
            </CardBody>
          </Card>
        </Col>
      </Row>
    )
  }
}

export default ReactTimeout(MetroAuditMain)

我通过延迟第二个组件的渲染来解决了这个问题。我不明白为什么有必要这样做,如果有人可以评论这将有所帮助。感谢