返回和转发时反应组件中的旧高图数据

时间:2018-04-19 15:54:16

标签: reactjs typescript highcharts redux

我创建了这个组件来显示Highchart。它用于仪表板组件。我从列表中导航到仪表板。

它几乎按预期工作,但并非完全如此。 如果我去仪表板买A项,一切都很好。如果Ithen按下后退按钮,然后导航到B项的仪表板 - 我会看到项目A的图表数据。如果我再次返回,并且要冲破C - 我会看到B的数据。 能找出我做错了什么的灵魂?

这是图表组件:

import * as React from 'react';
import * as Highcharts from "highcharts";

export interface IMyChartProps {
    options: Highcharts.Options;
}

type ChartProps = IMyChartProps;

export class MyChart extends React.Component<ChartProps, {}> {
    chart: Highcharts.ChartObject;
    container: HTMLDivElement | null;

    componentDidMount() {
        if (this.container) {
            this.chart = Highcharts.chart(this.container, this.props.options);
            { this.chart }
        }
    }

    componentWillUnmount() {
        this.chart && this.chart.destroy();
    }

    public render() {
        return <div ref={(div) => { this.container = div; }}></div>
    }
}

这是仪表板组件:

import * as React from 'react';
import { Link, RouteComponentProps, NavLink } from 'react-router-dom';
import { connect } from 'react-redux';
import { ApplicationState } from '../../store';
import * as PeopleGroupsStore from '../../store/Client/PeopleGroups';
import * as Highcharts from "highcharts";
import { MyChart, IMyChartProps } from '../Shared/MyChart';

type SubscriberDashboardProps =
    PeopleGroupsStore.PeopleGroupsState
    & typeof PeopleGroupsStore.actionCreators
    & RouteComponentProps<{ id: string }>;

interface SubscriberDashboardViewState {
    segmentIndex: number;
    lineChartData: IMyChartProps;
    colChartData: IMyChartProps;
}

class MyDashboard extends React.Component<MyDashboardProps, SubscriberDashboardViewState> {
    constructor(props: MyDashboardProps) {
        super(props);
        this.setupChartOptions();

        this.state = {
            segmentIndex: 0,
            lineChartData: {
                options: this.lineChartOptions
            },
            colChartData: {
                options: this.colChartOptions
            }
        }

        this.setSegmentIndex = this.setSegmentIndex.bind(this);
    }

    lineChartOptions: Highcharts.Options;
    colChartOptions: Highcharts.Options;

    setSegmentIndex(newIndex: number) {
        this.setState({ segmentIndex: newIndex });
    }

    componentWillMount() {
        this.props.requestPeopleGroups(this.props.match.params.id, 999);
    }

    shouldComponentUpdate(nextProps: MyDashboardProps, nextState: MyDashboardViewState) {
        if (this.props.PeopleGroups != nextProps.PeopleGroups) {
            this.updateOptions();
            return true;
        }

        if (this.state.segmentIndex != nextState.segmentIndex) {
            return true;
        }

        return false;
    }

    updateOptions() {
        let lineChartSeries: Array<Highcharts.LineChartSeriesOptions> = [];
        let columnChartSeries: Array<Highcharts.LineChartSeriesOptions> = [];
        let lineChartXAxisCategories: Array<string> = [];
        let xAxisCatFilled: boolean = false;

        this.props.PeopleGroups.forEach((ss) => {
            let d: Array<{ name: string, y: number }> = [];
            let totPeople: number = 0;
            ss.History.forEach((h) => {
                let yearWeek: string = h.Year.toString() + 'w' + h.Week.toString();
                d.push({ name: yearWeek, y: h.Count });
                if (!xAxisCatFilled) lineChartXAxisCategories.push(yearWeek);
                totPeople += h.Count;
            })
            lineChartSeries.push({
                name: ss.Name,
                data: d
            });
            columnChartSeries.push({
                name: ss.Name,
                data: [totPeople]
            });
            xAxisCatFilled = lineChartXAxisCategories.length > 0;
        });

        this.lineChartOptions.xAxis = { categories: lineChartXAxisCategories };
        this.lineChartOptions.series = lineChartSeries;
        this.colChartOptions.xAxis = { categories: [''] };
        this.colChartOptions.series = columnChartSeries;

        this.setState(
            {
                lineChartData: {
                    options: this.lineChartOptions
                },
                colChartData: {
                    options: this.colChartOptions
                }
            }
        );
    }

    public render() {
        return (
            <div>
                <div className="row">
                    {this.renderTable()}
                    {this.renderChart()}
                </div>
            </div>
        );
    }

    renderTable() {
        return (
            <div> ... omitted table rendering
            </div>);
    }

    renderChart() {
        this.updateOptions();

        return (
            <div>
                <div>
                    <div key="lineChartDiv"><MyChart options={this.state.lineChartData.options} ></MyChart></div>
                    <div key="colChartDiv"><MyChart options={this.state.colChartData.options} ></MyChart></div>
                </div>
            </div>
        );
    }

    setupChartOptions() {
        this.lineChartOptions = {
        //omitted setup
        };

        this.colChartOptions = {
        //omitted setup
        };
    }
}

export default connect(
    (state: ApplicationState) => state.PeopleGroups,
    PeopleGroupsStore.actionCreators
)(MyDashboard) as typeof MyDashboard;

编辑:更改为更一般的命名。

2 个答案:

答案 0 :(得分:1)

尝试使用componentDidMount生命周期挂钩而不是componentWillMount组件中的dashboard发出请求。

Dan's Abramov回答here相关,总而言之,如果您发送的内容会更改父项或兄弟会呈现的内容,则它们不会在当前呈现中呈现正确的内容,仅在下一个呈现时呈现就像你一样。

答案 1 :(得分:0)

如果有人遇到类似问题,我会回答我自己的问题。不确定它是不是一个合适的解决方案。

在我的图表组件中:

componentDidMount() {
    this.setupChart();
}

shouldComponentUpdate(nextProps: IMyChartProps) {
    if ((this.props.options && this.props.options.series) != this.chart.options.series) {
        this.setupChart();
        return true;
    }
    return false;
}

setupChart() {
    if (this.container) {
        this.chart = Highcharts.chart(this.container, this.props.options);
        { this.chart }
    }
}