2017-03-25 82 views
0

我無法繞過這個包裹我的頭。我正在編寫一個儀表板應用程序來反應。我試圖保持事物的好和模塊化。我有兩個佈局類「row.js」&「col.js」他們本質上是返回引導響應網格元素,「col-sm-3」等。反應通過組件提升狀態

我已經創建了一個窗口小部件類和一個窗口小部件展開類。小部件類返回帶有一些樣式的div,並且小部件可擴展類擴展小部件類並添加一個點擊處理程序以擴展到完整的瀏覽器寬度。然後,我創建自定義窗口小部件類,擴展這些窗口小部件類中的任一個這些自定義類將圖表或表格等添加到實際組件中。這個問題我嘗試修復是:

在我dashboard.jsx我:

<Row> 
    <Col size="sm" num="3"> 
     <SpeakerFees expanded={false}/> 
    </Col> 
    <Col size="sm" num="9"> 
     <ProgramStatusByZoneOverview /> 
    </Col> 
</Row> 

我想點擊widget組件,它傳遞到最近的祖先「」並提醒其他部件(s)在同一行中。根據反應提升狀態文件,我們應該提升到最近的祖先..在這種情況下,兩個要素。這是討厭的笑loll

因爲儀表板的佈局將只包含最多10個總的小部件,我想最好我只是在dashboard.jsx硬編碼這些,而不是有某種循環。以下是我的其他課程。

dashboard.jsx 

var React = require('react'); 
var ReactDOM = require('react-dom'); 

import { Row } from './layout/row.jsx'; 
import { Col } from './layout/col.jsx'; 

import { TotalWidget } from './widgets/total-widget.jsx'; 
import { ProgramsPlannedBySeries } from './widgets/programs-planned-by-series.jsx'; 
import { SpeakerFees } from './widgets/speaker-fees.jsx'; 
import { ProgramStatusByZoneOverview } from './widgets/program-status-by-zone-overview.jsx'; 

import 'bootstrap/dist/css/bootstrap.css'; 
import '../styles/app.scss'; 

class Dashboard extends React.Component { 
    render() { 
     var list = [ 
      { 
       "size": "sm", 
       "num": "3" 
      },{ 
       "size": "sm", 
       "num": "3" 
      },{ 
       "size": "sm", 
       "num": "3" 
      },{ 
       "size": "sm", 
       "num": "3" 
      } 
     ] 
     return (
      <div className="container"> 
       <Row> 
        {list.map(function(object, i){ 
         return (
          <Col key={i.toString()} size={object.size} num={object.num}><TotalWidget key={i.toString()} /></Col> 
         ); 
        })} 
       </Row> 
       <Row> 
        <Col size="sm" num="12"> 
         <ProgramsPlannedBySeries /> 
        </Col> 
       </Row> 
       <Row> 
        <Col size="sm" num="3"> 
         <SpeakerFees expanded={false}/> 
        </Col> 
        <Col size="sm" num="9"> 
         <ProgramStatusByZoneOverview /> 
        </Col> 
       </Row> 
       <Row> 
        <Col size="sm" num="3"> 
         <SpeakerFees expanded={false}/> 
        </Col> 
        <Col size="sm" num="9"> 
         <ProgramStatusByZoneOverview /> 
        </Col> 
       </Row> 
       <Row> 
        <Col size="sm" num="3"> 
         <SpeakerFees expanded={false}/> 
        </Col> 
        <Col size="sm" num="9"> 
         <ProgramStatusByZoneOverview /> 
        </Col> 
       </Row> 
      </div> 
     ); 
    } 
} 

ReactDOM.render(<Dashboard />, document.getElementById('widgets-wrapper')); 

和我的窗口小部件類:

widget.jsx 
var React = require('react'); 

import {TweenMax, Power2, TimelineLite} from "gsap"; 

export class WidgetMenu extends React.Component { 
    constructor() { 
     super(); 
     this.click = this.click.bind(this); 
    } 
    click() { 
     alert() 
    } 
    render() { 
     return (
      <span onClick={this.click} className={"glyphicon glyphicon-option-horizontal elipsis " + this.props.state} ></span> 
     ); 
    } 
} 

export class Widget extends React.Component { 
    constructor(props) { 
     super(props); 
     this.state = {'scale': false, 'class': ''}; 
     this.hover = this.hover.bind(this); 
    } 
    hover() { 
     if(!this.state.scale){ 
      this.setState({'scale': true, 'class': 'scaleUp'}) 
     }else{ 
      this.setState({'scale': false, 'class': ''}) 
     } 
    } 
    click() { 
     // alsert('widget') 
    } 
    render() { 
     return (
       <div onClick={this.click} onMouseEnter={this.hover} onMouseLeave={this.hover} className="widget"><WidgetMenu state={this.state.class} />{ this.props.children }</div> 
      ) 
    } 
} 

和widget-expandable.jsx

widget-expandable.jsx 
import { Widget, WidgetMenu } from './widget.jsx'; 
var React = require('react'); 

export class WidgetExpandable extends Widget { 
    constructor(props) { 
     super(props); 
    } 
    render() { 
     return (
      <div onMouseEnter={this.hover} onMouseLeave={this.hover} className="widget"><WidgetMenu state={this.state.class} />{ this.props.children }</div> 
     ) 
    } 

} 

這裏是兩個自定義部件,這將是彼此相鄰的字是cols /行在dashboard.jsx中:

speaker-fee.jsx 
"use strict"; 
var React = require('react'); 
var Highcharts = require('highcharts'); 

import { WidgetExpandable } from './widget-expandable.jsx'; 

export class SpeakerFees extends React.Component { 
    render() { 
     return (
      <WidgetExpandable handleClick={this.props.handleClick}> 
       <div id="speaker-fees-chart"></div> 
      </WidgetExpandable> 
     ); 
    } 
} 

program-status.jsx 
"use strict"; 
var React = require('react'); 
import { Widget } from './widget.jsx'; 

export class ProgramStatusByZoneOverview extends React.Component { 

    render() { 
     return (
      <Widget keyId={1}> 
       <table className="table" id="speaker-fees-table"> 
        <thead> 
         <tr> 
          <th>Speaker Fees, Travel...</th> 
          <th>Budgeted Spend</th> 
          <th>Actual Spend</th> 
          <th>Variance</th> 
         </tr> 
        </thead> 
        <tbody> 
         <tr> 
          <td>Fee For Service</td> 
          <td>250,000</td> 
          <td>150,000</td> 
          <td>-1.5%</td> 
         </tr> 
         <tr> 
          <td>Fee For Service</td> 
          <td>250,000</td> 
          <td>150,000</td> 
          <td>-1.5%</td> 
         </tr> 
         <tr> 
          <td>Fee For Service</td> 
          <td>250,000</td> 
          <td>150,000</td> 
          <td>-1.5%</td> 
         </tr> 
         <tr> 
          <td>Fee For Service</td> 
          <td>250,000</td> 
          <td>150,000</td> 
          <td>-1.5%</td> 
         </tr> 
         <tr> 
          <td>Fee For Service</td> 
          <td>250,000</td> 
          <td>150,000</td> 
          <td>-1.5%</td> 
         </tr> 
        </tbody> 
       </table> 
      </Widget> 
     ); 
    } 
} 

回答

0

我想通了。關鍵是從我的row.js類開始。我在row.js類上創建了一個click事件,它在行類上設置了expanded = false的狀態。然後繞過每個孩子並添加這個點擊處理程序作爲道具。然後添加這個道具作爲孩子們的點擊。

export class Widget extends React.Component { 
    constructor(props) { 
     super(props); 
     this.state = {'scale': false, 'class': ''}; 
     this.hover = this.hover.bind(this); 
    } 
    hover() { 
     if(!this.state.scale){ 
      this.setState({'scale': true, 'class': 'scaleUp'}) 
     }else{ 
      this.setState({'scale': false, 'class': ''}) 
     } 
    } 

    render() { 
     console.log(this.props.onExpandChange) 
     return (
       <div onClick={this.props.onExpandChange} onMouseEnter={this.hover} onMouseLeave={this.hover} className="widget"><WidgetMenu state={this.state.class} />{ this.props.children }</div> 
      ) 
    } 
} 

"use strict"; 
var React = require('react'); 

export class Col extends React.Component { 
    render() { 
     const childrenWithProps = React.Children.map(this.props.children, 
       (child) => React.cloneElement(child, { 
        onExpandChange: this.props.onExpandChange 
       }) 
      ); 
     return (
      <div className={"col-" + this.props.size + '-' + this.props.num}> 
       {childrenWithProps} 
      </div> 
     ); 
    } 
} 

"use strict"; 
var React = require('react'); 

export class Row extends React.Component { 
    constructor(props) { 
     super(props); 
     this.state = {expanded: false} 
     this.click = this.click.bind(this); 
    } 
    click() { 
     this.setState({"expanded": !this.state.expanded}); 
     console.log(this.state.expanded); 
    } 
    render() { 
     const childrenWithProps = React.Children.map(this.props.children, 
       (child) => React.cloneElement(child, { 
        onExpandChange: this.click 
       }) 
      ); 
     return (
      <div className="row">{ childrenWithProps }</div> 
     ) 
    } 
}