Skip to content

Commit

Permalink
feat(network): network can be used in standalone mode via the useNetw…
Browse files Browse the repository at this point in the history
…ork hook
  • Loading branch information
plouc committed Dec 31, 2021
1 parent 2b26bf3 commit 1b03cec
Show file tree
Hide file tree
Showing 4 changed files with 57 additions and 40 deletions.
2 changes: 1 addition & 1 deletion packages/network/src/Network.tsx
Expand Up @@ -49,14 +49,14 @@ const InnerNetwork = <N extends NetworkInputNode>({
)

const [nodes, links] = useNetwork<N>({
center: [innerWidth / 2, innerHeight / 2],
nodes: rawNodes,
links: rawLinks,
linkDistance,
repulsivity,
distanceMin,
distanceMax,
iterations,
center: [innerWidth / 2, innerHeight / 2],
nodeColor,
nodeBorderWidth,
nodeBorderColor,
Expand Down
2 changes: 1 addition & 1 deletion packages/network/src/NetworkCanvas.tsx
Expand Up @@ -47,14 +47,14 @@ const InnerNetworkCanvas = <N extends NetworkInputNode>({
)

const [nodes, links] = useNetwork<N>({
center: [innerWidth / 2, innerHeight / 2],
nodes: rawNodes,
links: rawLinks,
linkDistance,
repulsivity,
distanceMin,
distanceMax,
iterations,
center: [innerWidth / 2, innerHeight / 2],
nodeColor,
nodeBorderWidth,
nodeBorderColor,
Expand Down
84 changes: 46 additions & 38 deletions packages/network/src/hooks.ts
Expand Up @@ -4,6 +4,8 @@ import isString from 'lodash/isString'
import isNumber from 'lodash/isNumber'
import { forceSimulation, forceManyBody, forceCenter, forceLink } from 'd3-force'
import { useTheme } from '@nivo/core'
import { useInheritedColor } from '@nivo/colors'
import { commonDefaultProps } from './defaults'
import {
InputLink,
NetworkInputNode,
Expand All @@ -13,7 +15,6 @@ import {
NetworkComputedNode,
ComputedLink,
} from './types'
import { useInheritedColor } from '@nivo/colors'

const computeForces = <N extends NetworkInputNode>({
linkDistance,
Expand Down Expand Up @@ -51,45 +52,62 @@ const computeForces = <N extends NetworkInputNode>({
return { link: linkForce, charge: chargeForce, center: centerForce }
}

const useNodeColor = <N extends NetworkInputNode>(color: NetworkNodeColor<N>) =>
useMemo(() => {
if (typeof color === 'function') return color
return () => color
}, [color])

const useLinkThickness = <N extends NetworkInputNode>(thickness: NetworkLinkThickness<N>) =>
useMemo(() => {
if (typeof thickness === 'function') return thickness
return () => thickness
}, [thickness])

export const useNetwork = <N extends NetworkInputNode = NetworkInputNode>({
center,
nodes,
links,
linkDistance,
repulsivity,
distanceMin,
distanceMax,
center,
iterations,
nodeColor,
nodeBorderWidth,
nodeBorderColor,
linkThickness,
linkColor,
linkDistance = commonDefaultProps.linkDistance,
repulsivity = commonDefaultProps.repulsivity,
distanceMin = commonDefaultProps.distanceMin,
distanceMax = commonDefaultProps.distanceMax,
iterations = commonDefaultProps.iterations,
nodeColor = commonDefaultProps.nodeColor,
nodeBorderWidth = commonDefaultProps.nodeBorderWidth,
nodeBorderColor = commonDefaultProps.nodeBorderColor,
linkThickness = commonDefaultProps.linkThickness,
linkColor = commonDefaultProps.linkColor,
}: {
center: [number, number]
nodes: N[]
links: InputLink[]
linkDistance: NetworkCommonProps<N>['linkDistance']
repulsivity: NetworkCommonProps<N>['repulsivity']
distanceMin: NetworkCommonProps<N>['distanceMin']
distanceMax: NetworkCommonProps<N>['distanceMax']
center: [number, number]
iterations: NetworkCommonProps<N>['iterations']
nodeColor: NetworkCommonProps<N>['nodeColor']
nodeBorderWidth: NetworkCommonProps<N>['nodeBorderWidth']
nodeBorderColor: NetworkCommonProps<N>['nodeBorderColor']
linkThickness: NetworkCommonProps<N>['linkThickness']
linkColor: NetworkCommonProps<N>['linkColor']
linkDistance?: NetworkCommonProps<N>['linkDistance']
repulsivity?: NetworkCommonProps<N>['repulsivity']
distanceMin?: NetworkCommonProps<N>['distanceMin']
distanceMax?: NetworkCommonProps<N>['distanceMax']
iterations?: NetworkCommonProps<N>['iterations']
nodeColor?: NetworkCommonProps<N>['nodeColor']
nodeBorderWidth?: NetworkCommonProps<N>['nodeBorderWidth']
nodeBorderColor?: NetworkCommonProps<N>['nodeBorderColor']
linkThickness?: NetworkCommonProps<N>['linkThickness']
linkColor?: NetworkCommonProps<N>['linkColor']
}): [null | NetworkComputedNode<N>[], null | ComputedLink<N>[]] => {
// we're using `null` instead of empty array so that we can dissociate
// initial rendering from updates when using transitions.
const [currentNodes, setCurrentNodes] = useState<null | NetworkComputedNode<N>[]>(null)
const [currentLinks, setCurrentLinks] = useState<null | ComputedLink<N>[]>(null)

const centerX = center[0]
const centerY = center[1]

useEffect(() => {
const forces = computeForces<N>({
linkDistance,
repulsivity,
distanceMin,
distanceMax,
center,
center: [centerX, centerY],
})

const nodesCopy: N[] = nodes.map(node => ({ ...node }))
Expand Down Expand Up @@ -122,18 +140,20 @@ export const useNetwork = <N extends NetworkInputNode = NetworkInputNode>({
)

return () => {
// prevent the simulation from continuing in case the data is updated,
// would be a waste of resource.
simulation.stop()
}
}, [
centerX,
centerY,
nodes,
links,
linkDistance,
repulsivity,
distanceMin,
distanceMax,
iterations,
center[0],
center[1],
])

const theme = useTheme()
Expand Down Expand Up @@ -169,15 +189,3 @@ export const useNetwork = <N extends NetworkInputNode = NetworkInputNode>({

return [enhancedNodes, enhancedLinks]
}

export const useNodeColor = <N extends NetworkInputNode>(color: NetworkNodeColor<N>) =>
useMemo(() => {
if (typeof color === 'function') return color
return () => color
}, [color])

export const useLinkThickness = <N extends NetworkInputNode>(thickness: NetworkLinkThickness<N>) =>
useMemo(() => {
if (typeof thickness === 'function') return thickness
return () => thickness
}, [thickness])
9 changes: 9 additions & 0 deletions website/src/data/components/network/meta.yml
Expand Up @@ -12,8 +12,14 @@ Network:
- experimental
stories: []
description: |
A network component connecting nodes with links.
The responsive alternative of this component is `ResponsiveNetwork`.
Please note that you can also use the `useNetwork` React hook if you want
to handle the rendering by yourself, it accepts an object with almost
the same props as the component and returns computed nodes & links.
NetworkCanvas:
package: '@nivo/network'
tags:
Expand All @@ -28,3 +34,6 @@ NetworkCanvas:
The responsive alternative of this component is
`ResponsiveNetworkCanvas`.
Please note that you can also use the `useNetwork` React hook if you want
to handle the rendering by yourself, it accepts an object with almost
the same props as the component and returns computed nodes & links.

0 comments on commit 1b03cec

Please sign in to comment.