2017-12-07 22 views
0

내 사이트의 작업 세부 정보 표시를 관리하는 다소 큰 React 구성 요소가 있습니다.React 구성 요소의 반복 횟수가 많음

내가

  1. 스마트 한 구성 요소는 대화 상자를 열기위한 몇 가지 옵션이하고 싶으면 몇 가지가 있습니다. 각 대화 상자마다 별도의 열기 및 닫기 기능이 있습니다. 예를 들어 handleImageGridShowhandleImageGridClose입니다. 이 문제를 더욱 간결하게 처리 할 수있는 방법이 있습니까?
  2. 저는 작업에 대한 세부 정보를 보여주는 많은 프레젠테이션 구성 요소 (예 : ViewJobDetails)가 있습니다. 내 문제는 내가 각 구성 요소에 소품으로 전달해야하고 동일한 소품을 계속 반복해서 전달해야한다는 것입니다.
  3. firebase에서 데이터를로드 할 때 종종 유사한 검사를 수행해야합니다. 구성 요소를 렌더링하기 전에 데이터가 존재하는 경우 (e.g.this.state.selectedImageGrid && <ImageGridDialog />). 이것에 관해 더 이상 영리한 방법이 있습니까?

    가져 오기 import React, {Component} from 'react';

    import { withStyles } from 'material-ui/styles'; 
    import ViewJobAttachment from "../../components/jobs/viewJobAttachment"; 
    import ViewJobDetails from "../../components/jobs/viewJob/viewJobDetails"; 
    import ViewJobActions from "../../components/jobs/viewJob/viewJobActions"; 
    import ViewCompanyDetails from "../../components/jobs/viewJob/viewCompanyDetails"; 
    import ViewClientsDetails from "../../components/jobs/viewJob/viewClientsDetails"; 
    import ViewProductsDetails from "../../components/jobs/viewJob/viewProductsDetails"; 
    import ViewAttachmentDetails from "../../components/jobs/viewJob/viewAttachmentDetails"; 
    import ViewEventLogDetails from "../../components/jobs/viewJob/viewEventLogDetails"; 
    import ViewSummaryDetails from "../../components/jobs/viewJob/viewSummary"; 
    import {FirebaseList} from "../../utils/firebase/firebaseList"; 
    import SimpleSnackbar from "../../components/shared/snackbar"; 
    import {calculateTotalPerProduct} from "../../utils/jobsService"; 
    import BasicDialog from "../../components/shared/dialog"; 
    import ImageGrid from "../../components/shared/imageGrid"; 
    import Spinner from "../../components/shared/spinner"; 
    import ViewPinnedImageDialog from "../../components/jobs/viewEntry/viewPinnedImage"; 
    import { 
        Redirect 
    } from 'react-router-dom'; 
    
    const styles = theme => ({ 
        wrapper: { 
        marginBottom: theme.spacing.unit*2 
        }, 
        rightElement: { 
        float: 'right' 
        } 
    }); 
    
    const ImageGridDialog = (props) => { 
        return (
        <BasicDialog open={!!props.selectedImageGrid} 
           handleRequestClose={props.handleRequestClose} 
           fullScreen={props.fullScreen} 
           title={props.title} 
        > 
         <ImageGrid selectedUploads={props.selectedImageGrid} 
            handleClickOpen={props.handleClickOpen}/> 
        </BasicDialog> 
    ) 
    }; 
    
    class ViewJob extends Component { 
        constructor() { 
        super(); 
    
        this.state = { 
         currentJob: null, 
         entries: [], 
         promiseResolved: false, 
         attachmentDialogOpen: false, 
         openAttachment: null, 
         selectedImageGrid: false, 
         selectedPinnedImage: false, 
         showSnackbar: false, 
         snackbarMsg: '', 
         markedImageLoaded: false, 
         loading: true, 
         redirect: false 
        }; 
    
        this.firebase = new FirebaseList('jobs'); 
    
        this.handleJobStatusChange = this.handleJobStatusChange.bind(this); 
        this.handleImageGridShow = this.handleImageGridShow.bind(this); 
        this.handleImageGridClose = this.handleImageGridClose.bind(this); 
        this.handlePinnedImageClose = this.handlePinnedImageClose.bind(this); 
        this.handlePinnedImageShow = this.handlePinnedImageShow.bind(this); 
        this.handleMarkedImageLoaded = this.handleMarkedImageLoaded.bind(this); 
        this.handleRemove = this.handleRemove.bind(this); 
        this.pushLiveToClient = this.pushLiveToClient.bind(this); 
        } 
    
        componentDidMount() { 
        this.firebase.db().ref(`jobs/${this.props.id}`).on('value', (snap) => { 
         const job = { 
         id: snap.key, 
         ...snap.val() 
         }; 
         this.setState({ 
         currentJob: job, 
         loading: false 
         }) 
        }); 
    
        const previousEntries = this.state.entries; 
    
        this.firebase.db().ref(`entries/${this.props.id}`).on('child_added', snap => { 
         previousEntries.push({ 
         id: snap.key, 
         ...snap.val() 
         }); 
    
         this.setState({ 
         entries: previousEntries 
         }) 
        }); 
        } 
    
        handleRemove() { 
        this.firebase.remove(this.props.id) 
         .then(() => { 
         this.setState({redirect: true}) 
         }) 
        }; 
    
        pushLiveToClient() { 
        const updatedJob = { 
         ...this.state.currentJob, 
         'lastPushedToClient': Date.now() 
        }; 
        this.firebase.update(this.state.currentJob.id, updatedJob) 
         .then(() => this.handleSnackbarShow("Job pushed live to client")) 
        } 
    
        handleJobStatusChange() { 
        const newState = !this.state.currentJob.completed; 
        const updatedJob = { 
         ...this.state.currentJob, 
         'completed': newState 
        }; 
        this.firebase.update(this.state.currentJob.id, updatedJob) 
        } 
    
        handleSnackbarShow = (msg) => { 
        this.setState({ 
         showSnackbar: true, 
         snackbarMsg: msg 
        }); 
        }; 
    
        handleSnackbarClose= (event, reason) => { 
        if (reason === 'clickaway') { 
         return; 
        } 
        this.setState({ showSnackbar: false }); 
        }; 
    
        handleAttachmentDialogClose =() => { 
        this.setState({attachmentDialogOpen: false}) 
        }; 
    
        handleClickOpen = (file) => { 
        this.setState({ 
         attachmentDialogOpen: true, 
         openAttachment: file 
        }); 
        }; 
    
        handleImageGridShow(imageGrid) { 
        this.setState({selectedImageGrid: imageGrid}) 
        } 
    
        handleImageGridClose() { 
        this.setState({selectedImageGrid: false}) 
        } 
    
        handlePinnedImageShow(pinnedImage) { 
        this.setState({selectedPinnedImage: pinnedImage}) 
        } 
    
        handlePinnedImageClose() { 
        this.setState({selectedPinnedImage: false}) 
        } 
    
        handleMarkedImageLoaded() { 
        this.setState({markedImageLoaded: true}) 
        } 
    
        render() { 
        const {classes} = this.props; 
        let {_, costPerItem} = calculateTotalPerProduct(this.state.entries); 
        if (this.state.redirect) { 
         return <Redirect to='/jobs' push/> 
        } else { 
         if (this.state.loading) { 
         return <Spinner/> 
         } else { 
         return (
          <div className={styles.wrapper}> 
          {this.state.currentJob && 
          <div> 
           <ViewJobActions currentJob={this.state.currentJob} 
               handleJobStatusChange={this.handleJobStatusChange} 
               pushLiveToClient={this.pushLiveToClient} 
           /> 
           <ViewJobDetails currentJob={this.state.currentJob}/> 
           <ViewCompanyDetails currentJob={this.state.currentJob}/> 
           <ViewClientsDetails currentJob={this.state.currentJob}/> 
           <ViewProductsDetails currentJob={this.state.currentJob}/> 
           {this.state.currentJob.selectedUploads && this.state.currentJob.selectedUploads.length > 0 
           ? <ViewAttachmentDetails currentJob={this.state.currentJob} handleClickOpen={this.handleClickOpen}/> 
           : null} 
           <ViewEventLogDetails jobId={this.state.currentJob.jobId} 
                jobKey={this.state.currentJob.id} 
                entries={this.state.entries} 
                handlePinnedImageShow={this.handlePinnedImageShow} 
                handleImageGridShow={this.handleImageGridShow}/> 
           <ViewSummaryDetails stats={costPerItem}/> 
           <ViewJobAttachment open={this.state.attachmentDialogOpen} 
               handleRequestClose={this.handleAttachmentDialogClose} 
               attachment={this.state.openAttachment} 
           /> 
           {this.state.selectedImageGrid && 
           <ImageGridDialog selectedImageGrid={this.state.selectedImageGrid} 
               handleRequestClose={this.handleImageGridClose} 
               handleClickOpen={this.handleClickOpen} 
               title="Pictures for job" 
               fullScreen={false}/>} 
           {this.state.selectedPinnedImage && 
           <ViewPinnedImageDialog attachment={this.state.selectedPinnedImage} 
                open={!!this.state.selectedPinnedImage} 
                markedImageLoaded={this.state.markedImageLoaded} 
                handleMarkedImageLoaded={this.handleMarkedImageLoaded} 
                handleRequestClose={this.handlePinnedImageClose} 
                otherMarkedEntries={this.state.entries} 
           /> 
           } 
           <SimpleSnackbar showSnackbar={this.state.showSnackbar} 
               handleSnackbarClose={this.handleSnackbarClose} 
               snackbarMsg={this.state.snackbarMsg}/> 
    
          </div>} 
          </div> 
         ); 
         } 
        } 
        } 
    } 
    
    export default withStyles(styles)(ViewJob); 
    

답변

0

당신은 일반 구성 요소 방법을 정의하고

기능이

handler(index) { 
    ... 
} 
과 같아야 인덱스 VAR에서 몇 가지 구별 것은이 가정이 onSomething={this.handler.bind(this, index)} 같은 핸들러에 바인딩 할 수 있습니다