maslianok / react-resize-detector Goto Github PK
View Code? Open in Web Editor NEWA Cross-Browser, Event-based, Element Resize Detection for React
Home Page: http://maslianok.github.io/react-resize-detector/
License: MIT License
A Cross-Browser, Event-based, Element Resize Detection for React
Home Page: http://maslianok.github.io/react-resize-detector/
License: MIT License
Would you be interested in a PR to add an additional prop for the leading/trailing options for Lodash's throttle/debounce function? If yes, I can whip something up.
cd react-resize-detector/example
Should be
cd react-resize-detector/examples
I get the following error:
TypeError: Cannot read property 'parentElement' of null
at ResizeDetector.componentDidMount (node_modules/react-resize-detector/lib/components/ResizeDetector.js:97:105)
at commitLifeCycles (node_modules/react-test-renderer/cjs/react-test-renderer.development.js:6427:22)
at commitAllLifeCycles (node_modules/react-test-renderer/cjs/react-test-renderer.development.js:7516:7)
at HTMLUnknownElement.callCallback (node_modules/react-test-renderer/cjs/react-test-renderer.development.js:1881:14)
at invokeEventListeners (node_modules/jsdom/lib/jsdom/living/events/EventTarget-impl.js:193:27)
at HTMLUnknownElementImpl._dispatch (node_modules/jsdom/lib/jsdom/living/events/EventTarget-impl.js:119:9)
at HTMLUnknownElementImpl.dispatchEvent (node_modules/jsdom/lib/jsdom/living/events/EventTarget-impl.js:82:17)
at HTMLUnknownElementImpl.dispatchEvent (node_modules/jsdom/lib/jsdom/living/nodes/HTMLElement-impl.js:30:27)
at HTMLUnknownElement.dispatchEvent (node_modules/jsdom/lib/jsdom/living/generated/EventTarget.js:157:21)
at Object.invokeGuardedCallbackDev (node_modules/react-test-renderer/cjs/react-test-renderer.development.js:1919:16)
at invokeGuardedCallback (node_modules/react-test-renderer/cjs/react-test-renderer.development.js:1968:29)
at commitRoot (node_modules/react-test-renderer/cjs/react-test-renderer.development.js:7655:7)
at completeRoot (node_modules/react-test-renderer/cjs/react-test-renderer.development.js:8624:34)
at performWorkOnRoot (node_modules/react-test-renderer/cjs/react-test-renderer.development.js:8568:9)
at performWork (node_modules/react-test-renderer/cjs/react-test-renderer.development.js:8499:7)
at performSyncWork (node_modules/react-test-renderer/cjs/react-test-renderer.development.js:8471:3)
at requestWork (node_modules/react-test-renderer/cjs/react-test-renderer.development.js:8371:5)
at scheduleWork (node_modules/react-test-renderer/cjs/react-test-renderer.development.js:8248:11)
at scheduleRootUpdate (node_modules/react-test-renderer/cjs/react-test-renderer.development.js:8713:3)
at updateContainerAtExpirationTime (node_modules/react-test-renderer/cjs/react-test-renderer.development.js:8740:10)
at updateContainer (node_modules/react-test-renderer/cjs/react-test-renderer.development.js:8751:10)
at create (node_modules/react-test-renderer/cjs/react-test-renderer.development.js:9221:5)
at getRenderedTree (node_modules/@storybook/addon-storyshots/dist/react/renderTree.js:24:14)
at renderOnly (node_modules/@storybook/addon-storyshots/dist/test-bodies.js:73:16)
at Object.<anonymous> (node_modules/@storybook/addon-storyshots/dist/index.js:121:20)
I think this could be avoided by moving code out of componentDidMount
into the div
's ref
callback. I'll test this and raise a PR if it pans out.
Hi @maslianok!
Thanks for the very cool lib!
Right now this library only supports adding a resize detector on a parent element or a resizableElementId
. It would be nice if this were a bit more flexible and it would allow both a way to provide a selector that is not only just id
(for example using querySelector
) and allow for more than one selector to be added and I can listen to resize events on multiple elements. Thoughts?
The onResize will fire at first render.
Is it a browser default behaviour or this is ReactResizeDetector specific behaviour?
Thank you for your hard work!!
Does react-resize-detector
support CSS grids? I couldn't get react-resize-detector
to detect resize when the element is inside a grid.
Here's a downstream issue - recharts/recharts#1423
client?df36:168 ./node_modules/react-masonry-responsive/lib.es2015/index.js
Module not found: Error: Can't resolve 'react-resize-detector' in 'F:\ts\mingtuWebsite\node_modules\react-masonry-responsive\lib.es2015'
const path = require('path');
const webpack = require('webpack');
const HtmlWebpackPlugin = require('html-webpack-plugin');
const MiniCssExtractPlugin = require('mini-css-extract-plugin');
const OptimizeCSSAssetsPlugin = require('optimize-css-assets-webpack-plugin');
const tsImportPluginFactory = require('ts-import-plugin');
module.exports = {
mode: 'development',
entry: [
'react-hot-loader/patch',
'webpack-dev-server/client?http://localhost:8080/',
'webpack/hot/only-dev-server',
'./src/main.tsx',
],
output: {
filename: 'bundle.js',
path: path.join(__dirname, 'dist'),
publicPath: '/'
},
//devtool: 'inline-source-map',
devtool: 'eval-source-map',
resolve: {
extensions: ['.ts', '.tsx', '.js'],
},
module: {
rules: [
{
test: /\.tsx?$/,
loader: 'ts-loader',
exclude: /node_modules/,
include: path.resolve(__dirname, 'src'),
options: {
transpileOnly: true,
getCustomTransformers: () => ({
before: [tsImportPluginFactory({
libraryDirectory: 'es',
libraryName: 'antd',
style: 'css'
})],
}),
compilerOptions: {
module: 'es2015'
}
}
}
, {
test: /\.css?$/,
use: [
MiniCssExtractPlugin.loader,
"css-loader"
]
}
, {
test: /\.less?$/,
use: [
MiniCssExtractPlugin.loader,
{
loader: "typings-for-css-modules-loader",
options: {
modules: true,
namedExport: true,
camelCase: true,
}
},
"less-loader"
]
}
, {
test: /\.(png|jpeg|jpg|svg)$/i,
use: [
{
loader: 'url-loader',
options: {
limit: 8192,
name: 'imgs/[name].[hash].[ext]',
publicPath: '/'
}
}
]
}
, {
test: /\.(eot|ttf|woff|woff2)\w*/,
use: [
{
loader: 'file-loader'
}
]
}
, {
test: /\.(mp4|webm)$/,
use: 'file-loader?name=videos/[name].[ext]'
}
],
},
externals: {
},
plugins: [
new HtmlWebpackPlugin({
template: path.resolve(__dirname, 'src/index.html'),
inject: true,
})
, new webpack.HotModuleReplacementPlugin()
, new webpack.NamedModulesPlugin()
, new MiniCssExtractPlugin({
filename: "style.css",
chunkFilename: "[name].css"
})
, new webpack.WatchIgnorePlugin([
/css\.d\.ts$/
]),
require('autoprefixer')
],
optimization: {
minimizer: [
new OptimizeCSSAssetsPlugin({})
],
splitChunks: {
cacheGroups: {
vendor: {
test: /[\\/]node_modules[\\/]/,
name: 'common',
priority: 10,
chunks: 'all'
}
}
}
}
}
{
"compilerOptions": {
"sourceMap": true,
"lib": [
"es2015",
"dom",
],
"target": "es6",
"allowSyntheticDefaultImports": true,
"outDir": "./dist/",
"noImplicitAny": true,
"module": "esnext",
"moduleResolution": "node",
"jsx": "react",
"experimentalDecorators": true,
"resolveJsonModule": false
},
"include": [
"./src/**/*"
]
}
Hi There,
I'm just having a look at your plugin, it looks great but it doesn't play quite right with the Chrome Developer tools.
In your demo I can resize the main div by switching on mobile device emulation, the div doesn't react, and the resize count remains at zero. If I click the Toggle Left Panel button, then toggle the mobile device emulation the resize count starts incrementing as it should.
I'm sure this isn't a problem in the real world, but that is the first thing I did when I opened the demo.
Thanks
I'm looking to use this plugin in the context of the new Gutenberg editor for Wordpress. However, when I add this plugin I notice that I'm getting the following error:
Uncaught TypeError: Cannot read property 'insertBefore' of null
and the error is coming from the last line of this code.
function getScrollbarSizes() {
var width = 500;
var height = 500;
var child = document.createElement("div");
child.style.cssText = "position: absolute; width: " + width*2 + "px; height: " + height*2 + "px; visibility: hidden; margin: 0; padding: 0;";
var container = document.createElement("div");
container.style.cssText = "position: absolute; width: " + width + "px; height: " + height + "px; overflow: scroll; visibility: none; top: " + -width*3 + "px; left: " + -height*3 + "px; visibility: hidden; margin: 0; padding: 0;";
container.appendChild(child);
document.body.insertBefore(container, document.body.firstChild);
Is it possible to do a check to see if document.body is not null before running the insert?
Here's a library that fixed it in a similar fashion christophery/pushy#88
(I may submit a PR tonight or this weekend unless you can see any problem)
reactResizeRender = (width, height) => (
<div
style={{
height,
overflow: 'auto',
width: '100%'
}}
>
.....
</div>
);
render() {
return (
<ReactResizeDetector handleWidth handleHeight>
{(width, height) => <Fragment>{this.reactResizeRender(width, height)}</Fragment>}
</ReactResizeDetector>
);
}
I experienced 2 breaking changes when upgrading to v4. I am not sure they are worth maintaining compat for, but should be highlighted in release notes.
With v3, I could do this:
<ReactResizeDetector handleWidth>
width => <div>{width}</div>
</ReactResizeDetector>
This is no longer working with v4, you now need
<ReactResizeDetector handleWidth>
({width}) => <div>{width}</div>
</ReactResizeDetector>
This was working before:
<ReactResizeDetector handleWidth>
({width, height}) => <><div /><div /></>
</ReactResizeDetector>
Now that the implementation no longer inserts a <div>
, it is no longer working if the child function returns a fragment (which is implemented as an array iirc).
It may be worth checking the return value and log an error in console if this happens.
I think package should have a CI and test cases to easier enhancement it in future!
I tried a couple of ways to try and make resizableElementId
specify the window, but I could make it work. Is it possible to watch window resize events with this? It would be nice to be able to make use of the debounce/other features built in.
Version 4.0.1 has broken renderProps usage:
return (
<ReactResizeDetector
handleHeight
handleWidth
render={({height, width}) => (
<LineChart
width={width}
height={height - 30}
data={data}
>
...
hi @maslianok
Long time no see, I have maintained and contributed to some projects, so far I think it is time we need a major update on the performance and problems of this library. Can I refactor new version for lib using ref of React to wrap component instead of adding a new element and improve performance for lib? Maybe this is a big update for lib!
Warning: findDOMNode is deprecated in StrictMode. ... Instead, add a ref directly to the element you want to reference.
Would be a version with ref support?
Hi,
is there any way to init or enforce the width
and height
values for ReactResizeDetector
when performing tests ?
I'm using create-react-app
and it seems ReactResizeDetector
yield undefined
values when running automated tests.
Thanks.
It looks like react-resize-detector
strips all other props to the component.
render() {
const { shipmentKey } = this.props
return (
<Map testingProp={true} />
)
}
class Map extends Component {
constructor(props) {
super(props)
console.log('The props are: ', props)
}
}
export default withResizeDetector(Map)
These props are: {width: undefined, height: undefined}
How can we pass our own props through to our component?
<Table>
<ReactResizeDetector handleWidth handleHeight onResize={this.handleResize}/>
{rows}
</Table>
Table is display: table
Rows are each display: table-row
When a cell within a row resizes (I've got inputs in table-cells), the size of the ReactResizeDetector
div
changes, but no event is fired. The width of the RRD div
is the correct value.
this.handleResize
is bound in the constructor: this.handleResize = this.handleResize.bind(this);
. It simply doesn't get called except for when the table first renders.
There is a bug in Firefox which allows getComputedStyle
return null
in an iframe set to display: none
(see https://bugzilla.mozilla.org/show_bug.cgi?id=548397). In your ResizeDetector.js component, you can check for null before accessing the position
property to resolve this issue. This would be a really helpful fix for us, thanks.
if (parent.currentStyle) {
position = parent.currentStyle.position;
} else if (window.getComputedStyle && window.getComputedStyle(parent)) {
position = window.getComputedStyle(parent).position;
}
Hey there,
I went to try this out, but I couldn't without installing react-transform-hmr. It looks like your test and example build is leaking into your production build, since the published code probably should not have hot loading wrappings in it.
Thanks
Hi @maslianok, thanks for this great lib :)
I forked your code for replicate a issue in my recent project.
It's simply make the square fit to document body while resizing: http://davidguan.me/react-resize-detector/
Here is the code:
const s = {
wrapper: {
display: 'flex',
height: '100%',
width: '100%',
alignItems: 'center',
justifyContent: 'center',
},
target: {
width: 1,
height: 1,
background: 'skyblue',
},
};
class App extends Component {
state = {
scale: 1,
};
componentDidMount() {
// window.onresize = this.onResize;
}
onResize = () => {
const PADDING = 60;
const bodyWidth = document.body.offsetWidth;
const bodyHeight = document.body.offsetHeight;
const scale = (bodyWidth > bodyHeight ? bodyHeight : bodyWidth) - (2 * PADDING);
this.setState({ scale });
};
render() {
return (
<div style={s.wrapper}>
<div style={{ transform: `scale(${this.state.scale})`, ...s.target }} />
<ResizeDetector handleWidth handleHeight onResize={this.onResize} />
</div>
);
}
}
In Safari, if we drag browser windows to resize it, you can fell the square "jumps", if I simply uncomment // window.onresize = this.onResize;
, the "jumps" will gone.
Right now, the new dimension is always measured in pixels. Which is good, unless the contained object is variable (f.e. different font sizes). Having a 200 px wide container is acceptable for font 14, but difficult to accept for font 196. It would be good to express the size of the container in any unit relative to a font size.
I am getting a lot of "ResizeObserver loop limit exceeded" exceptions reported from my users (through Sentry).
It seems to only come from Chrome 64+ on mobile (so no polyfill).
WICG/resize-observer#38 gives a bit of context, and using requestAnimationFrame
seems to fix the bug (see cerner/terra-core#1647).
Would you be open to implement a fix for this?
Hi,
I am using react-resize-detector version 3.2.1 and it seems like no resize event is thrown when I resize my browser window vertically, even though handleHeight prop is set to true.
Here is my code:
<ReactResizeDetector
handleWidth
handleHeight
onResize={(width, height) => {
console.log("resize detected")
updateMapboxViewport({ width, height })
}}
>
<ReactMapGL
attributionControl={false}
mapStyle={mapboxStyle}
mapboxApiAccessToken={mapboxToken}
{...mapboxViewport}
onViewportChange={updateMapboxViewport}
>
<DeckGL {...mapboxViewport} layers={layers} />
</ReactMapGL>
</ReactResizeDetector>
In the following video, you can see that "resize detected" is logged to the console when I resize the browser window horizontally, but not when I resize it vertically.
react-resize-detector.webm.zip
Thanks in advance,
Quentin
Are there any plans to add support for "debounce"? Currently, when the browser is resized, the resize event fires multiple times. While that might be useful in some applications, I would rather have it only fire once or maybe twice, so that I don't unnecessarily start dozens or hundreds of components re-rendering more often than necessary.
<ReactResizeDetector handleWidth={true} handleHeight={true} onResize={this._onResize} />
this is my code, handleHeight didn't triggered.
Don't know why
As I said, should we return the width and height value on did mount component (when there is no resized)?
Hi, I'm using Recharts to implement some cool charts and using its responsive-container to make all the charts responsive, but I encountered some weird unexpected scrollbar inside the chart while resizing:
I inspected the HTML a little bit, and it's not related to SVG or recharts itself, it's actually caused by the DIVs that react-resize-detector creates.
So currently I just work around this issue to force all the divs that react-resize-detector creates to have the CSS style:
overflow: hidden
I am not sure why does this happen but looks like it begins after a ancestry element got the flex layout ( display: flex
).
Anyway, just let you know the issue, and also I kind of want to know why you have to use overflow: scroll
.
Hello,
Is it possible to remove the <div>
or whatever nodeType
was specified?
lodash.isarray has been deprecated, Array.isArray
should be used in index.js as per deprecation message.
Element
is not defined in node.js environment and should not be used directly.
ReferenceError: Element is not defined
at Object.<anonymous> (/home/fonger/front-end/node_modules/react-resize-detector/lib/components/ResizeDetector.js:273:70)
at Module._compile (internal/modules/cjs/loader.js:701:30)
at Object.Module._extensions..js (internal/modules/cjs/loader.js:712:10)
at Module.load (internal/modules/cjs/loader.js:600:32)
at tryModuleLoad (internal/modules/cjs/loader.js:539:12)
at Function.Module._load (internal/modules/cjs/loader.js:531:3)
at Module.require (internal/modules/cjs/loader.js:637:17)
at require (internal/modules/cjs/helpers.js:22:18)
at Object.<anonymous> (/home/fonger/front-end/node_modules/react-resize-detector/lib/index.js:14:46)
at Module._compile (internal/modules/cjs/loader.js:701:30)
at Object.Module._extensions..js (internal/modules/cjs/loader.js:712:10)
at Module.load (internal/modules/cjs/loader.js:600:32)
at tryModuleLoad (internal/modules/cjs/loader.js:539:12)
at Function.Module._load (internal/modules/cjs/loader.js:531:3)
at Module.require (internal/modules/cjs/loader.js:637:17)
at require (internal/modules/cjs/helpers.js:22:18)
ReferenceError: Element is not defined
at Object.<anonymous> (/home/fonger/front-end/node_modules/react-resize-detector/lib/components/ResizeDetector.js:273:70)
at Module._compile (internal/modules/cjs/loader.js:701:30)
at Object.Module._extensions..js (internal/modules/cjs/loader.js:712:10)
at Module.load (internal/modules/cjs/loader.js:600:32)
at tryModuleLoad (internal/modules/cjs/loader.js:539:12)
at Function.Module._load (internal/modules/cjs/loader.js:531:3)
at Module.require (internal/modules/cjs/loader.js:637:17)
at require (internal/modules/cjs/helpers.js:22:18)
at Object.<anonymous> (/home/fonger/front-end/node_modules/react-resize-detector/lib/index.js:14:46)
at Module._compile (internal/modules/cjs/loader.js:701:30)
at Object.Module._extensions..js (internal/modules/cjs/loader.js:712:10)
at Module.load (internal/modules/cjs/loader.js:600:32)
at tryModuleLoad (internal/modules/cjs/loader.js:539:12)
at Function.Module._load (internal/modules/cjs/loader.js:531:3)
at Module.require (internal/modules/cjs/loader.js:637:17)
at require (internal/modules/cjs/helpers.js:22:18)
I have a SPA with 2 routes, home and another page. On the another page, I have the react resize detector on the parent element(div) with skipOnMount set to true. When the browser is refreshed, the detector is created again with true, but when I try to navigate back to the previous route, the component is unmount but "createResizeHandler" is called, but skipOnMount is set to false and a setState still occurs.
The following then occurs:
"Warning: Can't perform a React state update on an unmounted component. This is a no-op, but it indicates a memory leak in your application. To fix, cancel all subscriptions and asynchronous tasks in the componentWillUnmount method."
Tracing through the source, noticed that global variable "this.skipOnMount = false;" during loop through of the createResizeHandler, during the forEach loop the global variable "this.skipOnMount" is set to false even though props.skipOnMount is true.
(xposting to react-size-observer
as it's an issue there as well
Apologies if someone has brought this up before. I've tried both react-resize-detector
and react-resize-observer
, and I'm using them in a way where I need it to live inside elements like <p>
and <span>
sometimes.
But React complains about this since it's against the HTML spec:
index.js:2178 Warning: validateDOMNesting(...): <div> cannot appear as a descendant of <p>.
It seems like the same functionality could be done with span
as long as it's set to display: block
. AFAIK spans are valid everywhere. Would it be worthwhile to switch?
2.0 triggers resize when component unmount
So the resize remain, if you modify props in -onResize, things will break!
The package crashes when using HOC implementation.
I've opened a PR #65 to fix it.
I needed to use v.2.3.0 since it is still backwards compatible w/ React 15.x, however I also needed to bundle the dependencies together into a UMD bundle. I'm able to provide a PR for changes off of the v2.3.0 tag, on my fork, however I cannot provide a PR back to this repo since there's no 2.3.x branch for git to compare to.
You can create a branch and publish it to github using the following commands from your repo:
git checkout v2.3.0
git checkout -b v2.3.x
git push -u origin v2.3.x
In my opinion, maybe need the following code in handleScroll
e.preventDefault();
e.stopPropagation();
I'd love if I could access the parent
element so I could add/remove a class depending on the proportions of the element.
I believe it could be done by passing entry.target
to onResize
.
Love the idea for this plugin, but I'm having trouble getting it to work predictably. I have a component like this:
export class Body extends Component{
onResize = (width) => {
console.log(width)
}
render(){
const {className = "", showDrawer = false, children} = this.props;
return(
<div className={"body container-fluid " + className + " " + (showDrawer ? "drawer-shown " : "")}>
<ReactResizeDetector handleWidth onResize={this.onResize} />
{children}
</div>
)
}
}
When I shrink the page it fires the resize event, but not when the page is expanded. Are there any requirements for the CSS of the parent element to make this work?
Hi there.
I'm trying to use your library to fire an event when one of my component has been resized, but I'm getting a weird error from React.
Here is my implementation:
render() {
return (
<div className="AuthForm">
<MyStuff />
<ReactResizeDetector onResize={ this.onResize }/>
</div>
);
}
and here is the error that I'm getting:
Error: Element type is invalid: expected a string (for built-in components) or a class/function (for composite components) but got: object.
Check the render method of `AuthForm`.
What am I doing wrong? Or is it an issue with the lib?
Thanks for help
Hi, I'm trying to use your component for determining the height of the document. Using the following code to log the width and height in the console to make sure everything is correct. The ReactResizeDetector
is at the top of my app rendering structure. So should fire always (also when content inside changes).
onResize(height, width) {
console.log(height, width);
}
However when testing it, the onResize event only fires when the viewport is larger than the one initially loaded. o.O
Since React v15.5 the PropTypes
are deprecated and when using this package this warning appears:
Warning: Accessing PropTypes via the main React package is deprecated. Use the prop-types package from npm instead.
I'm noticing a couple of issues with v4.0.5 and how the array of children are handled.
Each child in a list should have a unique "key" prop
warning:<ReactResizeDetector>
<Foo />
<Bar />
</ReactResizeDetector>
TypeError: element is null
:<ReactResizeDetector>
{ someBoolean ? <Foo /> : null }
<Bar />
</ReactResizeDetector>
Hi,
I'm not quite sure if it's an issue, but the .babelrc configuration is breaking my own .babelrc configuration, also jenkins is sending the same error.
The error that I got is this: Couldn't find preset "es2015" relative to directory "/xxx-xxxt/node_modules/react-resize-detector"
is there any way to avoid the manually delete?
Thanks.
[email protected] requires a peer of react@^0.14.7 || ^15.0.0 but none is installed. You must install peer dependencies yourself
Delaying onResize call with debounce can invoke setState on an unmounted component which causes warning from React.
Will be nice to add guard for this case.
This would save some code for me:
<ReactResizeDetector render={({ width, height }) => <MyComponent width={width} />}
I love this component and use it actively.
Maybe more patterns would make it even more flexible?
I can think of two :
A declarative, efficient, and flexible JavaScript library for building user interfaces.
đ Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. đđđ
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google â¤ī¸ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.