1

The component is using jQuery to get the element width which is working. This is a question about setting the wrapper div element in such a way that its dimensions change with a resize of the window. Currently it is always 600 px by 300 px.

I am trying to change the state of an SVG React component when the parent container reaches a certain size. The container is a React HOC named withResizeHandler and the wrapper node is a div element. The div size is checked with jquery from the callback updateSize triggered by the resize event. I change the browser window size and execution enters the callback but the console log indicates that the div never changes from it original dimensions of 600px by 300px. The code is on code pen https://codepen.io/pboulos/pen/rrLYKE?editors=0111.

const withResizeHandler = (WrappedComponent) => {
  return class extends React.Component {
    state = {
    width: 0,
    height: 0
  }
  //Init 
  componentWillMount(){
    console.log('HOC Resize Props',this.props);
    window.addEventListener("resize", this.updateSize.bind(this));
    this.setState({width:this.props.width, height:this.props.height});
  }

  componentDidMount() {
    this.updateSize();
  }

  componentWillUnmount(){
    $(window).off('resize');
  }

  updateSize = () => {
   // DOM node is the wrapper div element
   var node = ReactDOM.findDOMNode(this);
   const nodeWidth = $(node).width();
   const nodeHeight = $(node).height();
   console.log("Parent Width "+ nodeWidth+" Height "+nodeHeight);

   if (nodeWidth < this.props.width){
    this.setState({width: nodeWidth-20});
   }else{
     this.setState({width: this.props.width});
   } 
 }
 render () {
   return (
     <div style={{"height" : "300px"}}>
       {/* pass down the props from the hoc wrapper */}
       <WrappedComponent width={this.state.width} height={this.state.height}/>
    </div>
   );
  }
 }
}
Paul
  • 348
  • 2
  • 16
  • Possible duplicate of [How do I retrieve an HTML element's actual width and height?](https://stackoverflow.com/questions/294250/how-do-i-retrieve-an-html-elements-actual-width-and-height) – jmargolisvt Jul 21 '18 at 17:18
  • Not a duplicate, that question is about getting the element size which my implementation can already do using jquery width() method. – Paul Jul 21 '18 at 19:30
  • Your event listener and setting of state should be inside `componentDidMount` not `componentWillMount` – Komolafe Tolulope Jul 21 '18 at 19:32
  • Changed it, but still same outcome though. – Paul Jul 21 '18 at 19:45
  • I think if you read that question I marked as a dupe, you'll find your answer because it describes other methods of calculating width. You are currently reading the inline width that you are setting on your element. That's why it's not changing. – jmargolisvt Jul 21 '18 at 20:14

2 Answers2

0

A purely CSS solution is to use inline-size (it's still experimental) on all div nodes in the DOM hierarchy above the SVG component and below the App flex root. For the react style example:

<App>
  <div style={{"inlineSize":"75%"}}>
   <h3> Some Heading </h3>
    <div style={{"inlineSize":"75%"}}>
      <some SVG component>... </SVG>
    </div>
  <div>
</App>
Paul
  • 348
  • 2
  • 16
0

Set the CSS width and height as a percentage of the container on all nodes above the SVG component. Set the svg element style to display=block. Code pen example: https://codepen.io/pboulos/pen/wxqVwZ?editors=1111. So code relevant to answer would be:

 <CircleWrap  width={800} height={600}/>

 function CircleWrap(props) {
 return (
  <div style={{border: "1px solid white", margin: "auto", width: "90%", height: "90%"}}>
    <h3>SVG Circle</h3>
      <div style={{border: "1px solid black", padding: "3px", margin: "auto", width: "90%", height: "90%"}}>
        <ResizeCircle width={this.props.width} height={this.props.height}/>
      </div>
  </div>
);
}

let ResizeCircle = withResizeHandler(Circle);

function Circle(props) {
 return (<svg id={this.state.chartId} style={{display: 'block', margin: "auto", width: this.props.width, height: this.props.height}}>
     <g transform={transform}>
          <circle cx="70" cy="70" r="70"  fill="red"/>
     </g>
  </svg>  
);
}

const withResizeHandler = (WrappedComponent) => {
  return class extends React.Component {
  render () {
   return (
     <div style={{border: "1px solid red", margin: "auto", width: "100%", height: "100%"}}>
       {/* pass down the props from the hoc wrapper */}
       <WrappedComponent width={this.state.width} height={this.state.height}/>
     </div>
   );
 }

} }

Paul
  • 348
  • 2
  • 16