diff --git a/CHANGELOG.md b/CHANGELOG.md
index 57d56dbc1..c0252a5b2 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -8,6 +8,7 @@ Changelog
* ✨ Replaced inline `require` statement with header `import` in `Grid` for better integration with the Rollup module bundler. ([@odogono](https://github.com/odogono) - [#617](https://github.com/bvaughn/react-virtualized/pull/617))
* 🐛 Improved guard for edge-case scrolling issue with rubberband scrolling in iOS. ([@dtoddtarsi](https://github.com/offsky) - [#616](https://github.com/bvaughn/react-virtualized/pull/616))
* ✨ Replaced `getBoundingClientRect()` with slightly faster `offsetWidth` and `offsetHeight` inside of `AutoSizer`.
+* ✨ `AutoSizer` no longer re-renders nor calls `onResize` callback unless `width` and/or `height` have changed (depending on which properties are being watched).
##### 9.3.0
* 🎉 Added `resetLoadMoreRowsCache` method to `InfiniteLoader` to reset any cached data about loaded rows. This method should be called if any/all loaded data needs to be refetched (eg a filtered list where the search criteria changes). ([#612](https://github.com/bvaughn/react-virtualized/issues/612))
diff --git a/source/AutoSizer/AutoSizer.jest.js b/source/AutoSizer/AutoSizer.jest.js
index f4c6933f1..f9d33fc59 100644
--- a/source/AutoSizer/AutoSizer.jest.js
+++ b/source/AutoSizer/AutoSizer.jest.js
@@ -5,7 +5,7 @@ import { findDOMNode } from 'react-dom'
import { render } from '../TestUtils'
import AutoSizer from './AutoSizer'
-function ChildComponent ({ height, width, foo, bar }) {
+function DefaultChildComponent ({ height, width, foo, bar }) {
return (
{`width:${width}, height:${height}, foo:${foo}, bar:${bar}`}
)
@@ -14,10 +14,12 @@ function ChildComponent ({ height, width, foo, bar }) {
describe('AutoSizer', () => {
function getMarkup ({
bar = 123,
+ ChildComponent = DefaultChildComponent,
disableHeight = false,
disableWidth = false,
foo = 456,
height = 100,
+ onResize,
paddingBottom = 0,
paddingLeft = 0,
paddingRight = 0,
@@ -38,7 +40,11 @@ describe('AutoSizer', () => {
return (
-
+
{({ height, width }) => (
{
expect(rendered.textContent).toContain('width:300')
done()
})
+
+ describe('onResize and (re)render', () => {
+ it('should trigger when size changes', async (done) => {
+ const onResize = jest.fn()
+ const ChildComponent = jest.fn().mockImplementation(DefaultChildComponent)
+ const rendered = findDOMNode(render(getMarkup({
+ ChildComponent,
+ height: 100,
+ onResize,
+ width: 200
+ })))
+ ChildComponent.mockClear() // TODO Improve initial check in version 10; see AutoSizer render()
+ expect(onResize).toHaveBeenCalledTimes(1)
+ await simulateResize({ element: rendered, height: 400, width: 300 })
+ expect(ChildComponent).toHaveBeenCalledTimes(1)
+ expect(onResize).toHaveBeenCalledTimes(2)
+ done()
+ })
+
+ it('should only trigger when height changes for disableWidth == true', async (done) => {
+ const onResize = jest.fn()
+ const ChildComponent = jest.fn().mockImplementation(DefaultChildComponent)
+ const rendered = findDOMNode(render(getMarkup({
+ ChildComponent,
+ disableWidth: true,
+ height: 100,
+ onResize,
+ width: 200
+ })))
+ ChildComponent.mockClear() // TODO Improve initial check in version 10; see AutoSizer render()
+ expect(onResize).toHaveBeenCalledTimes(1)
+ await simulateResize({ element: rendered, height: 100, width: 300 })
+ expect(ChildComponent).toHaveBeenCalledTimes(0)
+ expect(onResize).toHaveBeenCalledTimes(1)
+ await simulateResize({ element: rendered, height: 200, width: 300 })
+ expect(ChildComponent).toHaveBeenCalledTimes(1)
+ expect(onResize).toHaveBeenCalledTimes(2)
+ done()
+ })
+
+ it('should only trigger when width changes for disableHeight == true', async (done) => {
+ const onResize = jest.fn()
+ const ChildComponent = jest.fn().mockImplementation(DefaultChildComponent)
+ const rendered = findDOMNode(render(getMarkup({
+ ChildComponent,
+ disableHeight: true,
+ height: 100,
+ onResize,
+ width: 200
+ })))
+ ChildComponent.mockClear() // TODO Improve initial check in version 10; see AutoSizer render()
+ expect(onResize).toHaveBeenCalledTimes(1)
+ await simulateResize({ element: rendered, height: 200, width: 200 })
+ expect(ChildComponent).toHaveBeenCalledTimes(0)
+ expect(onResize).toHaveBeenCalledTimes(1)
+ await simulateResize({ element: rendered, height: 200, width: 300 })
+ expect(ChildComponent).toHaveBeenCalledTimes(1)
+ expect(onResize).toHaveBeenCalledTimes(2)
+ done()
+ })
+ })
})
diff --git a/source/AutoSizer/AutoSizer.js b/source/AutoSizer/AutoSizer.js
index 426aaa8b6..ffef537cb 100644
--- a/source/AutoSizer/AutoSizer.js
+++ b/source/AutoSizer/AutoSizer.js
@@ -79,6 +79,18 @@ export default class AutoSizer extends PureComponent {
outerStyle.width = 0
}
+ /**
+ * TODO: Avoid rendering children before the initial measurements have been collected.
+ * At best this would just be wasting cycles.
+ * Add this check into version 10 though as it could break too many ref callbacks in version 9.
+ if (
+ height !== 0 &&
+ width !== 0
+ ) {
+ child = children({ height, width })
+ }
+ */
+
return (