2017-09-15 60 views
0

我是react/redux的初學者,我遇到了我的應用程序 的每一次調度行爲的奇怪行爲,例如,React-redux無限重新安裝組件

store.dispatch({type: 'no_matter_what_is_here'}); 

重新安裝所有組件即使存儲器的狀態不改變遍地和提供組件的無限再現(組分使用「連接」功能從「反應-終極版」庫)。

我使用這些庫:

"dependencies": { 
"babel-polyfill": "^6.3.14", 
"bluebird": "^3.4.1", 
"eventsource-polyfill": "^0.9.6", 
"font-awesome-webpack": "0.0.4", 
"history": "^4.7.2", 
"lodash": "^4.17.4", 
"material-ui": "^0.19.1", 
"moment": "^2.13.0", 
"prop-types": "^15.5.10", 
"react": "^15.6.1", 
"react-dom": "^15.6.1", 
"react-dropzone": "^3.5.1", 
"react-modal": "^1.4.0", 
"react-redux": "^5.0.2", 
"react-router": "^3.0.0", 
"react-router-dom": "^4.2.2", 
"react-router-redux": "^4.0.6", 
"react-scripts": "1.0.13", 
"react-tap-event-plugin": "^2.0.1", 
"redux": "^3.6.0", 
"superagent": "^3.1.0", 
"uuid": "^3.0.1" 
}, 

什麼是這種行爲的原因是什麼?例如,組分的

代碼(但它關注於應用程序的每個組件)

import React, { Component } from 'react'; 
import store from '../../store'; 
import PropTypes from 'prop-types'; 
import { connect } from 'react-redux'; 
import _ from 'lodash'; 
import { CircularProgress } from 'material-ui'; 
import debounce from '../../modules/debounce'; 
import { JobAddDialog } from '../job'; 
import WorkdeckPanel from './workdeckPanel'; 
import QueuedJobList from './queuedJobList'; 
import { Label, WarningDialog, InfoDialog } from '../controls'; 
import { setupActions, jobActions } from '../../actions'; 
import { 
    connectTask, 
    reConnectTask, 
    cancelTask, 
    loadStatus, 
    startTask, 
    pauseTask, 
    stopTask, 
    skipTask, 
    retryTask, 
} from '../../actions/printerActions'; 
import { getEnumName } from '../../modules/enumHelpers'; 
import { printerErrorTypeEnum, printerStatusEnum } from '../../constants'; 

class Status extends Component { 
    static get propTypes() { 
    return { 
     printer: PropTypes.shape({ 
     status: PropTypes.number.isRequired, 
     }), 
     jobs: PropTypes.shape({ 
     list: PropTypes.array.isRequired, 
     }).isRequired, 
     resources: PropTypes.shape({}).isRequired, 
    }; 
    } 

    static get defaultProps() { 
    return { 
     printer: {}, 
     jobs: { 
     list: [], 
     }, 
    }; 
    } 

    constructor(props) { 
    super(props); 
    this.state = { 
     showAddDialog: false, 
     showConfirm: false, 
     showStop: false, 
     selectedJobId: null, 
    }; 
    this.onJobSelected = this.onJobSelected.bind(this); 
    this.onStatusLoaded = this.onStatusLoaded.bind(this); 
    } 

    componentWillMount() { 
    store.dispatch({type: 'no_matter_what'}); 
    } 

    componentDidUpdate() { 
    const { printer } = this.props; 
    const { showAddDialog } = this.state; 
    const { isLoading, status } = (printer || {}); 
    if (!isLoading && !showAddDialog 
     && [printerStatusEnum.notResponding, printerStatusEnum.confirming, printerStatusEnum.suspended].indexOf(status) === -1) { 
     debounce(this.onStatusLoaded, 1000); 
    } 
    } 

    onStatusLoaded() { 
    const { jobs, printer } = this.props; 
    loadStatus(printer.updateDate) 
     .then((res) => { 
     const job = Object.assign({ id: -1 }, printer.job); 
     const newJob = res.job ? _.find(jobs.list, { id: res.job.id }) : { id: -1 }; 
     if (newJob.id !== job.id) { 
      return jobActions.loadJobs(); 
     } 
     return null; 
     }); 
    } 

    onJobSelected(selectedJobId) { 
    this.setState({ selectedJobId }); 
    } 

    render() { 
    const { jobs, printer, resources } = this.props; 
    const { selectedJobId, showAddDialog, showConfirm, showStop } = this.state; 
    return (
     <div className="statusContainer"> 
     <QueuedJobList {...{ 
      jobs, selectedJobId, onJobSelect: this.onJobSelected, onJobAdd:() => { this.setState({ showAddDialog: true }); }, 
     }} 
     /> 
     <WorkdeckPanel {...{ jobs, 
      printer, 
      selectedJobId, 
      resources, 
      onStartClick:() => { 
      if (printer.job && printer.status === printerStatusEnum.suspended) { 
       this.setState({ showConfirm: true }); 
      } else { 
       startTask(); 
      } 
      }, 
      onStopClick:() => { this.setState({ showStop: true }); }, 
     }} 
     /> 

     { [printerStatusEnum.initializing].indexOf(printer.status) !== -1 
      ? (<InfoDialog {...{ 
      title: resources.get('device.connecting.title'), 
      show: true, 
      onCancel: cancelTask }} 
      > 
      <div className="iconProgress"><CircularProgress thickness={5} /></div> 
      <h3 className="textAlert"> 
       <Label path="device.connecting.note" /> 
      </h3> 
      </InfoDialog>) 
      : null } 
     <JobAddDialog {...{ 
      show: showAddDialog, 
      isQueued: true, 
      onClose:() => { this.setState({ showAddDialog: false }); }, 
     }} 
     /> 
     <ConfirmDialog {...{ printer, showConfirm, onHide:() => { this.setState({ showConfirm: false }); }, resources }} /> 
     <NotRespondingDialog {...this.props} /> 
     <ErrorDialog {...{ showStop, onCancel:() => { this.setState({ showStop: true }); }, printer, resources }} /> 
     <StopDialog {...{ show: showStop, onClose:() => { this.setState({ showStop: false }); }, resources }} /> 
     </div> 
    ); 
    } 
} 

const ConfirmDialog = ({ printer, showConfirm, onHide, resources }) => { 
    const { status, method } = printer; 
    let onCancel = onHide; 
    let show = showConfirm; 
    if (status === printerStatusEnum.confirming) { 
    onCancel =() => { 
     onHide(); 
     cancelTask(); 
    }; 
    show = true; 
    } 
    if (show) { 
    return (
     <InfoDialog {...{ 
     title: resources.get('device.confirming.title'), 
     okCaption: resources.get('buttons.continue'), 
     show, 
     onCancel, 
     onOk:() => { 
      onHide(); 
      startTask(); 
     }, 
     }} 
     > 
     <Label {...{ path: 'device.confirming.note', replacements: method }} /> 
     </InfoDialog>); 
    } 
    return null; 
}; 

const NotRespondingDialog = (props) => { 
    const { resources, printer } = props; 
    if (printer.status === printerStatusEnum.notResponding) { 
    return (
     <WarningDialog {...{ 
     title: resources.get('device.notResponding.title'), 
     okCaption: resources.get('buttons.retry'), 
     show: true, 
     buttons: [ 
      { type: 'Cancel', onClick: cancelTask }, 
      { type: 'Retry', onClick: reConnectTask, isPrimary: true }, 
     ] }} 
     > 
     <Label path="device.notResponding.note" /> 
     </WarningDialog>); 
    } 
    return null; 
}; 

const ErrorDialog = ({ showStop, onCancel, printer, resources }) => { 
    const { status, errorType } = printer; 
    if (status === printerStatusEnum.inError && !showStop) { 
    const error = getEnumName(printerErrorTypeEnum, errorType); 
    let buttons = [ 
     { type: 'Ok', onClick: pauseTask, isPrimary: true }, 
    ]; 
    if (errorType === printerErrorTypeEnum.tubeError) { 
     buttons = [ 
     { type: 'Cancel', onClick: onCancel }, 
     { type: 'Skip', onClick: skipTask }, 
     { type: 'Retry', onClick: retryTask, isPrimary: true }, 
     ]; 
    } 
    return (
     <WarningDialog {...{ 
     title: resources.get(`device.${error}.title`), 
     show: true, 
     buttons }} 
     > 
     <Label {...{ path: `device.${error}.note` }} /> 
     </WarningDialog>); 
    } 
    return null; 
}; 

const StopDialog = ({ show, onClose, resources }) => { 
    if (show) { 
    return (
     <WarningDialog {...{ 
     title: resources.get('device.stopping.title'), 
     show: true, 
     buttons: [ 
      { type: 'Cancel', onClick: onClose }, 
      { type: 'Ok', onClick:() => { stopTask().then(() => { onClose(); }); }, isPrimary: true }, 
     ] }} 
     > 
     <Label className="textInfo" path="device.stopping.note" /> 
     </WarningDialog>); 
    } 
    return null; 
}; 

export default connect(
    state => ({ 
    jobs: state.jobs, 
    printer: state.printer, 
    resources: state.resources, 
    }), 
)(Status); 
+0

編輯後請把你的組件代碼,這聽起來可能嘗試在更新狀態組件更新的時刻。 –

回答

1

首先你應該此代碼分成表象COMPONENTES和容器。容器保持邏輯並與商店連接。這會讓你的代碼更容易出錯並且更容易閱讀。

關於您的問題,您可以撥打store.dispatch({type: 'no_matter_what'});聯繫componentWillMount。這不是一個好習慣,你可以閱讀here。我建議你從那裏刪除它。

另外,我會研究你在那裏的綁定。試着瞭解你是否真的需要他們,因爲他們是atm。我沒有足夠的知識,但我會研究this文章,這是相當不錯的(雖然不完美)。

在這種情況下,我建議你使用箭頭函數,並確保你需要這個onStatusLoaded綁定。你將它綁定在構造函數中,並且在onStatusLoaded裏面,每次組件更新時,你似乎都會再次更新狀態,這將導致一個循環。

+0

用componentDidMount替換componentWillMount,完成任務。 – frage

0

你的錯誤有可能在componentDidUpdate方法,你需要安慰每一步條件的所有值趕permament reconcollat​​ion: enter image description here