首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >加载新数据时删除d3-flame graph

加载新数据时删除d3-flame graph
EN

Stack Overflow用户
提问于 2020-08-25 00:55:30
回答 1查看 52关注 0票数 0

最近,我选择了一个包含d3-flame-graph的项目,该图形根据在另一个组件上定义的过滤器显示。我的问题是,当使用新参数进行搜索时,我似乎无法清理之前的图表,我想知道是否有人可以帮助我。基本上,我现在拥有的是,当我第一次进入页面时,加载组件,然后我有我的图表,当我搜索新的日期时,我有加载组件,但在上面我仍然有以前的图表

我想我可以在const updateGraph上使用flamegraph().destroy(),但是什么都没有发生

代码语言:javascript
复制
import React, { FC, useEffect, useRef, useState, useCallback } from 'react'
import { useParams } from 'react-router-dom'
import moment from 'moment'
import * as d3 from 'd3'
import { flamegraph } from 'd3-flame-graph'

import Filters, { Filter } from '../../../../../../components/Filters'
import { getFlamegraph } from '../../../../../../services/flamegraph'
import { useQueryFilter } from '../../../../../../hooks/filters'
import FlamegraphPlaceholder from '../../../../../../components/Placeholders/Flamegraph'

import css from './flamegraph.module.css'

import ToastContainer, {
  useToastContainerMessage,
} from '../../../../../../components/ToastContainer'

const defaultFilters = {
  startDate: moment().subtract(1, 'month'),
  endDate: moment(),
  text: '',
  limit: 10,
}

const getOffSet = (divElement: HTMLDivElement | null) => {
  if (divElement !== null) {
    const padding = 100
    const minGraphHeight = 450

    // ensure that the graph has a min height
    return Math.max(
      window.innerHeight - divElement.offsetTop - padding,
      minGraphHeight
    )
  } else {
    const fallBackNavigationHeight = 300

    return window.innerHeight - fallBackNavigationHeight
  }
}

const Flamegraph: FC = () => {
  const [queryFilters, setQueryFilters] = useQueryFilter(defaultFilters)
  const [fetching, setFetching] = useState(false)
  const [graphData, setGraphData] = useState()
  const {
    messages: toastMessages,
    addMessage: addMessageToContainer,
    removeMessage: removeMessageFromContainer,
  } = useToastContainerMessage()
  const flameContainerRef = useRef<HTMLDivElement | null>(null)
  const flameRef = useRef<HTMLDivElement | null>(null)
  const graphRef = useRef<any>()
  const graphDataRef = useRef<any>()
  const timerRef = useRef<any>()

  const { projectId, functionId } = useParams()
  let [sourceId, sourceLine] = ['', '']

  if (functionId) {
    ;[sourceId, sourceLine] = functionId.split(':')
  }

  const createGraph = () => {
    if (flameContainerRef.current && flameRef.current) {
      graphRef.current = flamegraph()
        .width(flameContainerRef.current.offsetWidth)
        .height(getOffSet(flameRef.current))
        .cellHeight(30)
        .tooltip(false)
        .setColorMapper(function(d, originalColor) {
          // Scale green component proportionally to box width (=> the wider the redder)
          let greenHex = (192 - Math.round((d.x1 - d.x0) * 128)).toString(16)
          return '#FF' + ('0' + greenHex).slice(-2) + '00'
        })
    }
  }

  const updateGraph = (newData: any) => {
    setGraphData(newData)
    graphDataRef.current = newData

    if (graphRef.current) {
      if (newData === null) {
        graphRef.current.destroy()
        graphRef.current = null
      } else {
        d3.select(flameRef.current)
          .datum(newData)
          .call(graphRef.current)
      }
    }
  }

  const fetchGraph = (filters: Filter) => {
    setFetching(true)
    getFlamegraph(
      Number(projectId),
      filters.startDate ? filters.startDate.unix() : 0,
      filters.endDate ? filters.endDate.unix() : 0,
      sourceId,
      sourceLine
    )
      .then(graphData => {
        if (!graphRef.current) {
          createGraph()
        }
        updateGraph(graphData)
      })
      .catch(({ response }) => {
        updateGraph(null)
        if (response.data) {
          addMessageToContainer(response.data.message, true)
        }
      })
      .finally(() => {
        setFetching(false)
      })
  }

  const onResize = useCallback(() => {
    clearTimeout(timerRef.current)
    timerRef.current = setTimeout(() => {
      if (graphRef.current && flameContainerRef.current) {
        graphRef.current.width(flameContainerRef.current.offsetWidth)
        d3.select(flameRef.current)
          .datum(graphDataRef.current)
          .call(graphRef.current)
      }
    }, 500)
  }, [])

  useEffect(() => {
    fetchGraph(queryFilters)
    window.addEventListener('resize', onResize)

    return () => {
      window.removeEventListener('resize', onResize)
    }
    // eslint-disable-next-line react-hooks/exhaustive-deps
  }, [])

  const onChangeFilters = (filters: Filter) => {
    setQueryFilters(filters)
    fetchGraph(filters)
  }

  return (
    <div className={css.host}>
      <Filters
        defaultValues={queryFilters}
        searching={fetching}
        onSearch={onChangeFilters}
      />
      <div className={css.flameBox}>
        <div className={css.flameContainer} ref={flameContainerRef}>
          <div ref={flameRef} />
        </div>
        {fetching || !graphData ? (
          <FlamegraphPlaceholder loading={fetching} />
        ) : null}
      </div>
      <ToastContainer
        messages={toastMessages}
        toastDismissed={removeMessageFromContainer}
      />
    </div>
  )
}

export default Flamegraph
EN

回答 1

Stack Overflow用户

发布于 2020-08-25 20:00:30

首先,flamegraph()创建了一个新的flamegraph实例,您需要使用graphref.current.destroy()。其次,你不想在数据已经加载的时候销毁它,而是在它开始加载的时候销毁它,对吧?因为这是一个需要时间的操作。

请考虑以下几点:

代码语言:javascript
复制
const cleanGraph = () => {
  if (graphref.current !== undefined) {
    graphref.current.destroy()
  }
}

const fetchGraph = (filters: Filter) => {
  setFetching(true)
  cleanGraph()
  getFlamegraph(
    Number(projectId),
    filters.startDate ? filters.startDate.unix() : 0,
    filters.endDate ? filters.endDate.unix() : 0,
    sourceId,
    sourceLine
  )
  ...
}
票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/63565430

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档