Search code examples
reactjsd3.jsreact-d3

ReactJS D3 chart not showing data mapped from Context, but works with static variable


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


Solution

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

    , [cohorts]);

    Please replace [cohorts] instead of [].