Demo

Prerequisite

a bit of understanding of these topics.

Get Started

open CodeSandbox in browser, signup if you don’t have an account. It is an amazing tool for prototyping and testing web application.

Step 0

Click create sandbox then choose “React”. It is the same template from the official create-react-app repo.

Add dependencies for styling components. I use react-emotion because it is very easy to write css.

Click Add Dependency and then search for

emotion

react-emotion

cuid

Step 1

Right click at src folder and create file named SizeObserver.js then create simple component that render children

import React from "react"; class SizeObserver extends React.Component {

render() {

return this.prop.children;

}

} export default SizeObserver;

Step 2

add constructor and method getBound()

class SizeObserver extends React.Component {

constructor(props) {

super(props);

this.id = props.name;

} getBound() {

const component = document.getElementById(this.id);

if (!component) {

return {};

}

const rect = component.getBoundingClientRect();

return {

left: rect.left,

top: rect.top + window.scrollY,

width: rect.width || rect.right - rect.left,

height: rect.height || rect.bottom - rect.top

};

}



render() {

return this.props.children;

}

}

we receive props name from parent that will be a component id. getBoundingClientReact is a method that return an object containing height , width , top , left that we will use in the near future.

Step 3

Now, we will change this.props.children to be a function because it is easier to control and adjust the component that will be tracked.

// SizeObserver.js ... render() {

return this.props.children(this.id);

} ...

Test observer in index.js

// index.js ...

import styled from 'react-emotion'; const Box = styled("div")({

width: 300,

height: 150,

background: "tomato",

fontSize: "2em",

fontWeight: "bold",

color: "#fff",

lineHeight: "150px"

}); function App() {

return (

<div className="App">

<SizeObserver name="test">

{id => <Box id={id}>Box</Box>}

</SizeObserver

</div>

);

}

Step 4

update observer all the time.

// SizeObserver.js ... componentDidMount() {

this.intervalUpdate = setInterval(this.updatePosition, 50);

} componentWillUnmount() {

clearInterval(this.intervalUpdate);

} updatePosition = () => {

this.forceUpdate();

}; ... render() {

return (

const bound = this.getBound()

console.log(bound)

return this.props.children(this.id);

)

}

...

Now you get the size and position of the component, it is time to display it.

Step 5

create Label component that will display width & height of the Box. You can create a new file, but for demonstration purpose I will add it inside SizeObserver.js .

// SizeObserver.js const Label = styled('div')({

position: 'fixed',

background: 'rgba(0,0,0,0.5)',

color: '#fff',

padding: 8,

zIndex: 100,

'*': {

margin: 0,

}

})

Then use Portal to render the Label outside the Box to keep the Box clean. Refactor render method to this

// SizeObserver.js ... render() {

const bound = this.getBound()

console.log(bound)

return (

<React.Fragment>

{ReactDOM.createPortal(

<Label

style={{

top: bound.top,

left: bound.left,

}}

>

<p>w: {bound.width}</p>

<p>h: {bound.height}</p>

</Label>,

this.mountNode

)}

{this.props.children(this.id)}

</React.Fragment>

);

} ...

Ta dah!. That’s right baby.

Testing

the most easiest way to test observer is to use css resize: both to the Box

resize: 'both',

overflow: 'auto', // do not forget to add overflow: auto, otherwise won't work

resizable indicator at the bottom right corner

Drag it to see changes. Tell me it works. Hola, Woo hoo.

Finally

If you want to track multiple components, the code will get ugly because you need to write SizeObserver with children as a function all the time. This is where HOC plays an important role here.

create new file named withSizeObserver.js

I also add cuid() in SizeObserver.js because I want it to auto-gen id if no name from props provided.

This is the result.

That’s all of it. Thank you for reading. I will use SizeObserver for my next story:

Understanding Flex before using it. Stay tuned!

Feel free to comment below and ask anything! I’d be happy to help 👍

Source code for SizeObserver, thank you Code Sandbox.