Skip to content

Commit

Permalink
add: initial dimension to ResponsiveContainer (#3596)
Browse files Browse the repository at this point in the history
## Description

ResponsiveContainer component is used to render charts that can adapt to
their container. When a chart is rendered inside Responsive container,
you can omit its own height and width, and instead specify the
dimensions on the Container, one of the dimensions should be a
percentage, using `%` symbol, for instance 50%, recharts then tries to
to render the chart accordingly. This is possible because when the
component renders in the browser, then it'll calculate the container's
dimensions, and then it'll calculate the width (or the height) that was
specified in percentage.

When this ResponsiveContainer renders initially, its internal sizes are
sepcified as `{ width: -1, height: -1 }`, this is because it needs to
render in the browser before it can calculate the dimentions. Also,
ResponsiveContainer doesn't render the chart initialy since the
dimentions are negative, so it'll try to find a positive height and
width and render the chart accordingly.

This is important, because it means that, ResponsiveContainer relies on
JavaScript and Browser functionalities to calculate its children size,
and initially, it doesn't render the children. This can be a limitation
when the ResponsiveContainer functionality is needed but the charts are
rendered in an environment which is not the browser or JavaScript is not
available.

## Related Issue

Fixes #3595

## Motivation and Context

In this commit, I'm changed this behavior such that, initial height and
initial width can be specified to calculate the initial dimensions of
the ResponsiveContainer's child. These props, if not provided, they have
the original sizes (-1, -1) respectively, so this changes can be applied
without breaking semver.

Its important to note that, these two props should be either provided or
omitted together, because if either *width* or *height* negative, then
ResponsiveContainer will render null until it'll calculate the
dimensions on the client (Browser) after hydration.

Which means, its possible to render the charts in specified dimensions
while rendering on server, and initial render on browser (before
hydration), and when hydrated, the sizes will be calculated as before.

## How Has This Been Tested?

Its possible to test this in any framework that is capable to render on
server, and on client, but its also possible to enable and disable
JavaScript. I chose Remix to test this since disabling and enabling is
easily done by rendering or not rendering a component.


Use [this
example](https://stackblitz.com/edit/remix-run-remix-ugpuar?file=app%2Froot.tsx)
and comment out the `<Scripts />` on line **28** to see how the chart
looks when its server rendered but not hydrated.

Currently, it should render nothing when `<Scripts />` is not rendered.

When this changes applied, it should render with inital dimensions. 

## Screenshots (if appropriate)

## Types of changes

- [ ] Bug fix (non-breaking change which fixes an issue)
- [X] New feature (non-breaking change which adds functionality)
- [ ] Breaking change (fix or feature that would cause existing
functionality to change)

## Checklist

- [X] My code follows the code style of this project.
- [X] My change requires a change to the documentation.
- [X] I have updated the documentation accordingly.
- [X] All new and existing tests passed.
  • Loading branch information
akamfoad committed May 23, 2023
1 parent 245715d commit 1890285
Showing 1 changed file with 10 additions and 2 deletions.
12 changes: 10 additions & 2 deletions src/component/ResponsiveContainer.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,10 @@ export interface Props {
height?: string | number;
minWidth?: string | number;
minHeight?: string | number;
initialDimension?: {
width: number;
height: number;
};
maxHeight?: number;
children: ReactElement;
debounce?: number;
Expand All @@ -35,6 +39,10 @@ export const ResponsiveContainer = forwardRef(
(
{
aspect,
initialDimension = {
width: -1,
height: -1,
},
width = '100%',
height = '100%',
/*
Expand All @@ -56,8 +64,8 @@ export const ResponsiveContainer = forwardRef(
containerWidth: number;
containerHeight: number;
}>({
containerWidth: -1,
containerHeight: -1,
containerWidth: initialDimension.width,
containerHeight: initialDimension.height,
});

const containerRef = useRef<HTMLDivElement>(null);
Expand Down

0 comments on commit 1890285

Please sign in to comment.