Реагировать - Показать компонент после нажатия кнопки - PullRequest
0 голосов
/ 29 апреля 2018

Я использую material-ui и react-charts-js для создания страницы, которая извлекается из бэкэнда и отображает данные.

У меня возникли проблемы с пониманием того, как правильно отображать MyGraph.

Страница содержит два Date Picker, Toggle и Raised Button. Я хотел бы отобразить во втором Tab график после того, как данные выбраны и пользователь нажал на кнопку, затем сбросил данные и повторил снова.

Это некоторые попытки, но при этой стратегии MyGraph отображается правильно, но когда он вызывает this.props.onCreated(), this.state.buttonClicked ложно и график скрыт.

MyCard.js

import React from 'react';
import {Card, Tabs, Tab, FontIcon, DatePicker, Toggle, GridList, GridTile, SelectField, MenuItem, RaisedButton} from 'material-ui/';
import MyGraph from './MyGraph';

const styles = {
    root: {
        display: 'flex',
        flexWrap: 'wrap',
        justifyContent: 'space-around',
        margin: '0 auto'
    },
    gridList: {
        width: 200,
        height: 500,
        overflowY: 'auto',
    },
};

export default class MyCard extends React.Component {
    constructor(props){
        super(props)

        this.state = {
            queryNumber: 1,
            startDate: null,
            endDate: null,
            sameRegion: true,
            buttonDisabled: true,
            buttonClicked: false
        }
    }

    handleQueryNumberChange = (event, index, value) => {
        this.setState({queryNumber: value});
    }

    check(){
        if (this.state.startDate && this.state.endDate) {
            this.setState({buttonDisabled: false})
        }
    }

    handleStartDateChange = (event, date) => {
        this.setState({
            startDate: date,
        }, this.check);
    };

    handleEndDateChange = (event, date) => {
        this.setState({
            endDate: date,
        }, this.check);
    };

    handleSameRegionChange = (event, isInputChecked) =>{
        this.setState({sameRegion: isInputChecked});
    }

    handleClick = (event) =>{
        this.setState({buttonClicked: true})
    }

    resetForm = () =>{
        this.setState({buttonClicked: false, startDate: null, endDate: null, buttonDisabled: true})
    }

    render() {
        return (
            <Card>
                <Tabs>
                    <Tab icon={<FontIcon className="material-icons" >date_range</FontIcon>} label="Pick">
                        <div style={styles.root}>
                            <GridList
                                cols={1}
                                cellHeight={100}
                                padding={1}
                                style={styles.gridList}
                            >
                                <GridTile>
                                    <SelectField
                                        floatingLabelText="Query"
                                        value={this.state.queryNumber}
                                        onChange={this.handleQueryNumberChange}
                                    >
                                        <MenuItem value={1} primaryText="Date" />
                                        <MenuItem value={2} primaryText="Query2" />
                                        <MenuItem value={3} primaryText="Query3" />
                                        <MenuItem value={4} primaryText="Query4" />
                                        <MenuItem value={5} primaryText="Query5" />
                                    </SelectField>
                                </GridTile>
                                <GridTile>
                                    <DatePicker hintText="Select start date" value={this.state.startDate} onChange={this.handleStartDateChange}/>
                                </GridTile>
                                <GridTile>
                                    <DatePicker hintText="Select end date" value={this.state.endDate} onChange={this.handleEndDateChange}/>
                                </GridTile>
                                <GridTile>
                                    <Toggle label="Same Region" defaultToggled={true} onToggle={this.handleSameRegionChange}/>
                                </GridTile>
                                <GridTile>
                                    <RaisedButton label="Send" secondary={true} disabled={this.state.buttonDisabled} onClick={this.handleClick}/>
                                </GridTile>
                            </GridList>
                        </div>
                    </Tab>
                    <Tab icon={<FontIcon className="material-icons" >pie_chart</FontIcon>} label="Graph">
                        <div>
                            {this.state.buttonClicked && <MyGraph values={this.state} onCreated={this.resetForm}/>}
                        </div>
                    </Tab>
                </Tabs>
            </Card>
        );
    }
}

MyGraph.js

import React from 'react';
import {Pie} from 'react-chartjs-2';
import moment from 'moment'

export default class MyGraph extends React.Component {
    constructor(props) {
        super(props);

        this.state = {
            data: props,
            labels: [],
            datasets: [{
                data: [],
                backgroundColor: [
                    '#d50000',
                    '#2962ff',
                    '#00c853',
                    '#ffab00'
                ],
                hoverBackgroundColor: [
                    '#ff5252',
                    '#448aff',
                    '#69f0ae',
                    '#ffd740'
                ]
            }]
        }
    }

    call(){
        this.callApi()
            .then(res => {
                console.log(res)
                let datasetsModified = this.state.datasets;
                let labelsModified = this.state.labels;

                datasetsModified[0].data.length = 0;
                labelsModified.length = 0;

                for(let resource of res){
                    datasetsModified[0].data.push(resource.avg)
                    labelsModified.push(resource._id)
                }

                this.setState({
                    labels: labelsModified,
                    datasets: datasetsModified,
                })

            })
            .then(() =>{
                this.props.onCreated()
            })
            .catch(err => console.log(err))
    }

    async callApi(){
        var query = 'http://localhost:3100/api/pings/query/avgInDay?start='+moment(this.state.data.values.startDate).format('YYYY-MM-DD')+'&end='+moment(this.state.data.values.endDate).format('YYYY-MM-DD')+'&sameRegion='+((this.state.data.values.sameRegion === true) ? 0 : 1)
        const response = await fetch(query);
        const body = await response.json();

        return body;
    }

    componentDidMount(){
        this.call()
    }

    componentWillReceiveProps(nextProps) { // Successives rendering
        console.log('will')
        this.setState({data: nextProps}, this.call())
    }

    render() {
        return (
            <Pie data={this.state} width={500} height={500} options={{maintainAspectRatio: false}}/>
        );
    }
}

Кто-нибудь может проиллюстрировать правильный способ сделать это?

Заранее спасибо:)

РЕДАКТИРОВАТЬ 1: Я пытался поднять состояние, он делает то, что я хочу, но MyGraph вызывается при каждом изменении до щелчка; это нормально?

И, наконец, мои метки и данные обновляются, но не фрагменты

MyCard.js

import React from 'react';
import {Card, Tabs, Tab, FontIcon, DatePicker, Toggle, GridList, GridTile, SelectField, MenuItem, RaisedButton} from 'material-ui/';
import MyGraph from './MyGraph';
import moment from "moment/moment";

const styles = {
    root: {
        display: 'flex',
        flexWrap: 'wrap',
        justifyContent: 'space-around',
        margin: '0 auto'
    },
    gridList: {
        width: 200,
        height: 500,
        overflowY: 'auto',
    },
};

export default class MyCard extends React.Component {
    constructor(props){
        super(props)

        this.state = {
            queryNumber: 1,
            startDate: null,
            endDate: null,
            sameRegion: true,
            buttonDisabled: true,
            buttonClicked: false,
            graphData: {
                data: props,
                labels: [],
                datasets: [{
                    data: [],
                    backgroundColor: [
                        '#d50000',
                        '#2962ff',
                        '#00c853',
                        '#ffab00'
                    ],
                    hoverBackgroundColor: [
                        '#ff5252',
                        '#448aff',
                        '#69f0ae',
                        '#ffd740'
                    ]
                }]
            }
        }
    }

    handleQueryNumberChange = (event, index, value) => {
        this.setState({queryNumber: value});
    }

    check(){
        if (this.state.startDate && this.state.endDate) {
            this.setState({buttonDisabled: false})
        }
    }

    handleStartDateChange = (event, date) => {
        this.setState({
            startDate: date,
        }, this.check);
    };

    handleEndDateChange = (event, date) => {
        this.setState({
            endDate: date,
        }, this.check);
    };

    handleSameRegionChange = (event, isInputChecked) =>{
        this.setState({sameRegion: isInputChecked});
    }

    handleClick = (event) =>{
        this.callApi()
            .then(res => {
                console.log(res)
                let graphDataModified = this.state.graphData;
                let datasetsModified = graphDataModified.datasets;
                let labelsModified = graphDataModified.labels;

                datasetsModified[0].data.length = 0;
                labelsModified.length = 0;

                for(let resource of res){
                    datasetsModified[0].data.push(resource.avg)
                    labelsModified.push(resource._id)
                }

                this.setState({graphData: graphDataModified, buttonClicked: true})

            })
            .then(() =>{
                this.resetForm()
            })
            .catch(err => console.log(err))
    }

    async callApi(){
        var query = 'http://localhost:3100/api/pings/query/avgInDay?start='+moment(this.state.startDate).format('YYYY-MM-DD')+'&end='+moment(this.state.endDate).format('YYYY-MM-DD')+'&sameRegion='+((this.state.sameRegion === true) ? 0 : 1)
        const response = await fetch(query);
        const body = await response.json();

        return body;
    }

    resetForm = () =>{
        this.setState({startDate: null, endDate: null, buttonDisabled: true})
    }

    render() {
        return (
            <Card>
                <Tabs>
                    <Tab icon={<FontIcon className="material-icons" >date_range</FontIcon>} label="Pick">
                        <div style={styles.root}>
                            <GridList
                                cols={1}
                                cellHeight={100}
                                padding={1}
                                style={styles.gridList}
                            >
                                <GridTile>
                                    <SelectField
                                        floatingLabelText="Query"
                                        value={this.state.queryNumber}
                                        onChange={this.handleQueryNumberChange}
                                    >
                                        <MenuItem value={1} primaryText="Date" />
                                        <MenuItem value={2} primaryText="Query2" />
                                        <MenuItem value={3} primaryText="Query3" />
                                        <MenuItem value={4} primaryText="Query4" />
                                        <MenuItem value={5} primaryText="Query5" />
                                    </SelectField>
                                </GridTile>
                                <GridTile>
                                    <DatePicker hintText="Select start date" value={this.state.startDate} onChange={this.handleStartDateChange}/>
                                </GridTile>
                                <GridTile>
                                    <DatePicker hintText="Select end date" value={this.state.endDate} onChange={this.handleEndDateChange}/>
                                </GridTile>
                                <GridTile>
                                    <Toggle label="Same Region" defaultToggled={true} onToggle={this.handleSameRegionChange}/>
                                </GridTile>
                                <GridTile>
                                    <RaisedButton label="Send" secondary={true} disabled={this.state.buttonDisabled} onClick={this.handleClick}/>
                                </GridTile>
                            </GridList>
                        </div>
                    </Tab>
                    <Tab icon={<FontIcon className="material-icons" >pie_chart</FontIcon>} label="Graph">
                        <div>
                            { this.state.buttonClicked ? <MyGraph data={this.state.graphData}/> : null }
                        </div>
                    </Tab>
                </Tabs>
            </Card>
        );
    }
}

MyGraph.js

import React from 'react';
import {Pie} from 'react-chartjs-2';

export default class MyGraph extends React.Component {
    render() {
        console.log(this.props.data)
        return (
            <Pie data={this.props.data} width={500} height={500} options={{maintainAspectRatio: false}}/>
        );
    }
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...