javascriptreactjschartist.jsreact-chartist

How to map over an array of multiple objects for graphing?


I have an API response that provides multiple objects in an array:

[{"symbol":"AAPL","date":"2020-02-27","adj_close":68.24}, 
 {"symbol":"TSLA","date":"2020-02-27","adj_close":133.8}, 
 {"symbol":"TSLA","date":"2020-02-28","adj_close":122.3}, 
 {"symbol":"AAPL","date":"2020-02-28","adj_close":64.09}, 
 {"symbol":"TSLA","date":"2020-03-02","adj_close":137.33}, 
 {"symbol":"AAPL","date":"2020-03-02","adj_close":69.43}, 
 {"symbol":"TSLA","date":"2020-03-03","adj_close":143.22},
  ...
] 

I'm trying to create a map() that graphs each unique symbol from the response, for each <card> that already maps through another array of data. Like so:

enter image description here But as you can see, the mapping function I've made for my graphs does not work. It's stacking all of the data for each unique symbol onto each card. I would like each unique symbol to have it's own data graphed. I haven't been able to succeed, I have made a reproducible code below:

reproduceable code:https://codesandbox.io/s/gallant-curie-5qck3?file=/src/index.js

Here is how I set up everything:

Parents.js

export function MiniGraphDisplay(props)
{
    const { data } = props;
    const { slug } = useParams();
    const [historicalPrice, setHistoricalPrice] = useState([]);

    const fetchData = useCallback(async () =>
    {
        const response = await axiosInstance.get('bucket/graph-price/' + slug)
        const result = response.data;
        setHistoricalPrice(result);
    }, [])

    useEffect(() =>
    {
        fetchData();
    }, []);

    return (
        <>
        <Container maxWidth="lg" component="main">
            <Grid container spacing={5} alignItems="flex-end">
                {data[0]?.map((data,index) => {
                    return (
                        <Grid item key={index} xs={4} md={4}>
                            <Card>
                            <CardHeader
                            title={<Chip label={data.symbol} />} 
                            subheader={data.adj_close}        
                            />      
                            <CardContent >
                                <div>
                                <MiniGraphs historicalPrice={historicalPrice} />
                                </div>              
                            </CardContent>
                            </Card>
                        </Grid>
                    );
                })}
            </Grid>
        </Container>
        </>
    );
}

Child.js

export function MiniGraphs(props)
{
  const { historicalPrice } = props;

  const getChartData = () =>
  {
    const labels = [];
    const series = [];

    historicalPrice.forEach((item,) =>
    {
      labels.push(item.date);
      series.push(item.adj_close);
    });

    return {
      labels: labels,
      series: [series]
    };
  };

  // Add graph configuration here
  const chartOptions = {
    // width: 2000,
    height: 200,
    // scaleMinSpace: 20
    onlyInteger: true,
    showPoint: false,
    axisX: {
      labelInterpolationFnc: function (value, index)
      {
        return index % 32 === 0 ? value : null;
      },
    }
  };

  return (
    <>
      { historicalPrice && <ChartistGraph data={getChartData()} options={chartOptions} type="Line" />}
    </>
  );
}

Solution

  • Just working off your Sandbox here. The first thing to fix, it appears, is to only pass the relevant data to your MiniGraphs component. That can be done by:

    ...
    <CardContent>
      <div>
        <MiniGraphs
          historicalPrice={response.filter(
          (i) => i.symbol === data.symbol
          )}
        />
      </div>
    </CardContent>
    ...
    

    The other thing you seem to be missing, at least in your Sandbox, is proper styling for your graphs. So I added the contents of this file https://cdnjs.cloudflare.com/ajax/libs/chartist/0.11.4/chartist.min.css to the styles.css files in the Sandbox.

    The result seems to be what you're looking for: https://codesandbox.io/s/young-https-tol8c?file=/src/App.js