<div id="root"></div>
body {
	margin: 0;
}
const { useState, useRef, useCallback, useEffect } = React

const useMutationObserver = (elements, callback, config) => {
	useEffect(() => {
		const mutationObserver = new MutationObserver((mutations) => {
			mutationObserver.disconnect();
			callback(mutations);
			for (const elem of elements) {
				elem.current && mutationObserver.observe(elem.current, config);
			}
		});

		for (const elem of elements) {
			elem.current && mutationObserver.observe(elem.current, config);
		}

		return () => mutationObserver.disconnect();
	}, []);
};

const StyledElement = styled.div`
	background-color: red;
	height: 40vmin;
	position: relative;
	left: ${({count}) => count}px;
	width: 40vmin;
`

const App = () => {
	const [left, setLeft] = useState(0)
	const [count, setCount] = useState(0)
	const element = useRef(null)
	const style = {
		backgroundColor: "red",
		height: `40vmin`,
		position: `relative`,
		left: `${count}px`,
		width: `40vmin`
	}
	
	const handleUpdatePosition = (mutations) => {
		const left = mutations[0].target.getBoundingClientRect().left
		setLeft(left)
	}
	
	useMutationObserver(
		[element],
		handleUpdatePosition,
		{ attributes: true }
	)
	
	useEffect(() => {
		setInterval(() => setCount(prev => prev + 1), 1000)
	}, [])
	
	return (
		<div className="App">
			<div>left: {left}</div>
			<StyledElement
				ref={element}
				//style={style}
				count={count}
			/>
		</div>
	)
}

ReactDOM.render(<App />, document.getElementById('root'))
View Compiled
Run Pen

External CSS

This Pen doesn't use any external CSS resources.

External JavaScript

  1. https://cdnjs.cloudflare.com/ajax/libs/react/17.0.1/umd/react.production.min.js
  2. https://cdnjs.cloudflare.com/ajax/libs/react-dom/17.0.1/umd/react-dom.production.min.js
  3. https://cdnjs.cloudflare.com/ajax/libs/styled-components/4.3.1/styled-components.min.js