0

New to D3 and React.

I'm trying to show data on a grid (x/y axis) for each record against a background image (logo), showing a small images. I've got the D3 graph working if I use static data (gcs in my example code below). But, if I try to filter/map the data from CohortContext, the elements are not being shown on the graph. I think it's a timing issue that the D3 is rendering before the .map returns with the data, but I may be wrong. I tried wrapping the useEffect in an async, but I'm grasping at straws now and it didn't resolve the issue anyway, based on all the code being within the async.

The code:

import React, { useEffect, useContext } from "react"
import * as d3 from "d3"
import logo from '../../assets/images//charts/360Chart.svg'
import CohortContext from "../../utility/context/cohort/cohort-context"
import Saboteur from '../../assets/images/charts/chartBubbleKey.svg'

function ChartData({ goal }) {
    const gcs = [
        {
            chartAsset: Saboteur,
            xCoordinates: 200,
            yCoordinates: 300
        },
        {
            chartAsset: Saboteur,
            xCoordinates: 150,
            yCoordinates: 150
        }
    ]
    console.log(gcs)
    const width = 800
    const height = 800
    const { cohorts } = useContext(CohortContext) 
    
    useEffect(() => {
        //Retrieve the Goal data from the useContext
        const fetchData = async () => {
            const goalCohorts = cohorts
                            .filter(records => records.goalId === goal.goalId)
                            .map((records) => {
                                return {
                                chartAsset: Saboteur,
                                xCoordinates: records.xcoordinates,
                                yCoordinates: records.ycoordinates
                                }
                            })

        console.log('goal cohorts for Chart :', goalCohorts)

        const svg = d3
            .select("#svgcontainer")
            .append("svg")
            .attr("width", width)
            .attr("height", height)

        //background Chart
        svg
            .append("svg:image")
            .attr("xlink:href", () => logo)
            .attr("width", 580)
            .attr("height", 580)
            .attr("x", 110)
            .attr("y", 20)

        // Add in the data for the chart data
        const g = svg
            .selectAll("g")
            .append("g")
            .data(goalCohorts)  // works if I use .data(gcs)
            .enter()

        g.append("svg:image")
            .attr("xlink:href", (data) => data.chartAsset)
            .attr("width", 50)
            .attr("height", 50)
            .attr("x", (data) => data.xCoordinates)
            .attr("y", (data) => data.yCoordinates)
        }
        fetchData()
    }, [])

    return (
        < div className="App" >
            <div id="svgcontainer"></div>
        </div >
    )
}

export default ChartData

If I look at the console.logs, the data is the same - so assuming a timing issue. Can anyone see anything obvious on why data(goalCohorts) is not showing the data?

I'm using React v18.1, D3 v7.8

Clarkie
  • 39
  • 7

1 Answers1

0
useEffect(() => {
        //Retrieve the Goal data from the useContext
        const fetchData = async () => {
            const goalCohorts = cohorts
        .....

, [cohorts]);

Please replace [cohorts] instead of [].

  • Not really sure why, but add [cohorts] in isolation didn't resolve the issue. The useEffect was only firing before the data population. I have resolve the timing issue by running the data fetch useEffect in a function first and then passing as props to the chart as a second phase. The data volumes will always be small for this chart, so no real performance hit. Thanks for helping out, it did help figure out a solution. – Clarkie Feb 15 '23 at 22:16