【问题标题】:React Lifting Sate Up Through Components通过组件反应提升状态
【发布时间】:2017-03-25 17:19:45
【问题描述】:

我很难理解这一点。我正在编写一个仪表板应用程序来进行反应。我试图让事情变得美好和模块化。我有两个布局类“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>

我想单击小部件组件,将其传递给最近的祖先“”并提醒同一行中的其他小部件。根据反应提升状态文档,我们应该提升到最近的祖先......在这种情况下,两个元素向上。这很烦人哈哈

因为仪表板的布局最多只包含大约 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>
        )
    }

}

这里有两个自定义小部件,它们是dashboard.jsx 中的cols/rows:

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>
        );
    }
}

【问题讨论】:

    标签: reactjs react-native react-router react-redux


    【解决方案1】:

    我想通了。关键是从我的 row.js 类开始。我在 row.js 类上创建了一个 click 事件,该事件在 row 类上设置了 expand=false 的状态。然后循环遍历每个孩子并将此单击处理程序添加为道具。然后将此道具添加为孩子的onclick。

    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>
            )
        } 
    }
    

    【讨论】:

      猜你喜欢
      • 2023-02-06
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2019-05-18
      • 1970-01-01
      • 2018-07-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多