Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

d3Force is not a function #481

Open
egorairo opened this issue Dec 11, 2023 · 2 comments
Open

d3Force is not a function #481

egorairo opened this issue Dec 11, 2023 · 2 comments

Comments

@egorairo
Copy link

egorairo commented Dec 11, 2023

Hi! I'm trying to use d3force method but have error "d3Force is not a function". Could you please explain me why I am getting the error in the code below.

import React, { useEffect, useRef } from 'react';
import dynamic from 'next/dynamic';

const ForceGraph2D = dynamic(() => import('react-force-graph-2d'), {
  ssr: false,
});

const data = {
  nodes: [{ id: 'A' }, { id: 'B' }, { id: 'C' }, { id: 'D' }],
  links: [
    { source: 'B', target: 'C', value: 8 },
    { source: 'C', target: 'D', value: 10 },
    { source: 'D', target: 'A', value: 6 },
    { source: 'B', target: 'A', value: 6 },
    { source: 'B', target: 'D', value: 6 },
    { source: 'D', target: 'D', value: 6, curvature: 0.3 },
  ],
};

export default function App() {
  const forceRef = useRef(null);

  useEffect(() => {
    forceRef.current.d3Force('charge').strength(-400);
  });

  return (
    <ForceGraph2D
      graphData={data}
      nodeLabel="id"
      linkCurvature="curvature"
      enablePointerInteraction={true}
      linkDirectionalParticleWidth={1}
      ref={forceRef}
    />
  );
}
@vasturiano
Copy link
Owner

@egorairo you need to check whether your ref is defined before using it. It seems like in this case it is not. Specifically when you're using SSR this is quite important as refs tend to be defined only on the client side.

@samjusaitis
Copy link

samjusaitis commented Jan 22, 2024

@egorairo I ran into a similar problem using Next.js and trying to dynamically import this package.

Couple things that got it working for me:

  1. Had to ensure I was using a workaround like this one to ensure the ref was getting properly attached to the force graph.
  2. Even with this workaround, the ref wasn't available on the first render (unsure why). So I added further logic to check for this:
'use client';

import { useEffect, useReducer, useRef, useState } from 'react';
import { forceY } from 'd3-force';
import ForceGraph2D from './ForceGraph2D';

export const Graph = props => {
    const { data } = props;

    const graphRef = useRef(null);

    const [hasInitialisedForces, setHasInitialisedForces] = useState(false);
    const [tick, incrementTick] = useReducer(v => v + 1, 0);

    useEffect(() => {
        const graph = graphRef.current;

        if (!graph || hasInitialisedForces) return;

        graph.d3Force('center', null);
        graph.d3Force('directional', forceY(100));

        setHasInitialisedForces(true);
    }, [tick, hasInitialisedForces]);

    return (
        <ForceGraph2D
            ref={graphRef}
            graphData={data}
            onEngineTick={incrementTick}
        />
    );
};

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants