1

目前正在学习 React 和 D3。我有以下代码:

应用程序.js

import React, {useRef, useEffect, useState, Component} from 'react';
// import logo from './logo.svg';
import './App.css';

import ChartWrapper from './ChartWrapper'

class App extends Component() {
  render() {
    return (
      <div id="app">
        <ChartWrapper data = {[10, 13, 9.5, 11, 12, 14, 8, 13, 15, 14]}/>
      </div>
    )
  }
}

export default App;

ChartWrapper.js

import React, {Component, useEffect, useState} from 'react';
import { useRef } from 'react';
import LineChart from './LineChart'

function ChartWrapper(props)  {
    const [data, setData] = useState(props.data);
    const svgRef = useRef();
    //let data = [10, 13, 9.5, 11, 12, 14, 8, 13, 15, 14];
    console.log("works");

    useEffect( () => {
        const chart = new LineChart(svgRef, data);
        console.log(data);
    }, [data]);

    function updateChart(value) {
        data.push(value);
    }

    return (
        <div>
            <svg ref={svgRef} height = {300} width = {500}></svg>
        <button onClick={() => setData(data.map(value => value + 5))}>Update Data</button>
        </div>

    );
}

export default ChartWrapper;

LineChart.js

import React, {Component} from 'react'
import {line, select, selectAll, axisBottom, ScaleLinear, scaleLinear} from 'd3';

class LineChart {
    constructor (parent, data) {
        this.svg = select(parent.current);
        this.data = data;
        this.line  = this.getLine();
        this.xScale = this.getXScale();
        this.yScale = this.getYScale();

        // Plot the chart
        this.plot();
    }

    getLine() {
        return line()
                .x((value, index) => this.xScale(index))
                .y(value => this.yScale(value));
    }

    getXScale() {
        return scaleLinear()
                .domain([0, this.data.length - 1])
                .range([0, this.svg.attr('width')]);
    }

    getYScale() {
        return scaleLinear()
                .domain([0, 20])
                .range([this.svg.attr('height'), 0]);
    }


    plot() {
        this.svg.selectAll('path')
                .data([this.data])
                .join('path')
                .attr('d', value => this.line(value))
                .attr('fill', 'none')
                .attr('stroke', 'purple');
    }

}

export default LineChart;

我想知道是否有可能以某种方式从“App.js”文件中调用“ChartWrapper.js”中的 updateChart() 函数,因为我希望能够随时更新图表值(而不是呈现整个再次页面)?

假设您从服务器获取实时值并需要实时更新图表,那么创建灵活图表组件的最佳方法是什么?

4

1 回答 1

2

您可以同时定义 state hook 和updateChartin App.js,然后将它们ChartWrapper.js作为 props 传递:

// App.js

import React, { useState } from 'react';
import './App.css';

import ChartWrapper from './ChartWrapper'

const App = () => {
  const [data, setData] = useState([10, 13, 9.5, 11, 12, 14, 8, 13, 15, 14]);
  function updateChart() {
    setData(data.map(value => value + 5));
  }

  return (
    <div id="app">
      <ChartWrapper data={data} updateChart={() => updateChart()}/>
    </div>
  )
}

export default App;
// ChartWrapper.js

import React, { useEffect, useRef } from 'react';
import LineChart from './LineChart'

function ChartWrapper({ data, updateChart })  {

    const svgRef = useRef();
    //let data = [10, 13, 9.5, 11, 12, 14, 8, 13, 15, 14];
    console.log("works");

    useEffect( () => {
        const chart = new LineChart(svgRef, data);
        console.log(data);
    }, [data]);

    return (
        <div>
            <svg ref={svgRef} height = {300} width = {500}></svg>
        <button onClick={() => updateChart()}>Update Data</button>
        </div>

    );
}

export default ChartWrapper;

另请注意,您不应该像现在那样在数组上使用.pushdataupdateChart应该setData像在onClick回调中那样使用。

希望这可以帮助。祝你好运!

于 2020-05-19T15:42:24.043 回答