2017-09-15 5 views
0

私はreact/reduxの初心者で、私のアプリケーションの奇妙な動作に出くわしました。 アクションをディスパッチするたびに試行されます。React-redux無限再マウントコンポーネント

ストアの状態が何度も変更して成分の無限レンダリング(成分「反応-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を読むことは良い習慣ではありません。私はそこからそれを削除することをお勧めします。

また、私はそこにあるそれらのバインディングを調べます。彼らが本当に必要なのかどうか理解してみてください。私は十分な知識がありませんが、かなり良い(完全ではありませんが)thisの記事を見ていきます。

この場合、矢印機能を使用して、このonStatusLoadedバインディングが必要であることを確認することをお勧めします。あなたはコンストラクタでそれをバインドしていて、onStatusLoadedの場合は、コンポーネントが更新されるたびに状態を更新しているように見えます。サイクルが発生します。

+0

componentWillMountをcomponentDidMountに置き換えて、完了しました。 – frage

0

componentDidUpdate方法で可能性があなたの間違いは、あなたがpermament reconcollat​​ionキャッチする条件に各段階にすべての値をコンソールする必要があります。 enter image description here