Search code examples
reactjstypescriptreact-functional-componentvictory-charts

Using custom container with functional component


I have defined a custom container:

const CombinedContainer = createContainer("selection", "voronoi");

const selectionStyle = {
  fill: "transparent",
  fillOpacity: 0.5,
  stroke: "red",
  strokeWidth: 1
}

type Props = {}

const ChartContainer = (props: Props) => (
  <CombinedContainer
    // @ts-ignore
    cursorDimension="x"
    selectionDimension="x"
    selectionStyle={selectionStyle}
    labels={({datum}) => `${datum.x}, ${datum.y.toFixed(2)} ${datum.volume}`}
  />
)

export default ChartContainer;

and using it like this:

<VictoryChart
  width={width}
  padding={padding}
  minDomain={{ y: 70 }}
  maxDomain={{ y: dataSet.maxDomain }}
  containerComponent={<ChartContainer />}
>
  ...
</VictoryChart>

but this doesn't render anything unless I use it like a normal function:

<VictoryChart
  width={width}
  padding={padding}
  minDomain={{ y: 70 }}
  maxDomain={{ y: dataSet.maxDomain }}
  containerComponent={ChartContainer({})}
>
  ...
</VictoryChart>

I have previously defined similar function components and used them without any problems but I can't see what am I doing wrong here. Can anyone help me?

Why <ChartContainer /> doesn't work but ChartContainer() does?

createContainer function is defined as:

export type ContainerType =
  | "brush"
  | "cursor"
  | "selection"
  | "voronoi"
  | "zoom";
export function createContainer<V, W>(
  c1: ContainerType,
  c2: ContainerType
): React.ComponentType<V & W>;

Here is the sample project to test it:

https://github.com/olcayertas/victory-functional-container-componenet


Solution

  • It doesn't work because ChartContainer doesn't pass received props (and doesn't render the children).

    So just {...props} on CombinedContainer:

    const ChartContainer = (props: Props) => (
      <CombinedContainer
        // @ts-ignore
        cursorDimension="x"
        selectionDimension="x"
        selectionStyle={selectionStyle}
        // @ts-ignore
        labels={({ datum }) =>
          `Date: ${datum.date}\nPrice: $${datum.close.toFixed(2)}\nVolume: ${
            datum.volume
          }`
        }
        {...props}
      />
    );
    

    Working example