简体   繁体   中英

Calling setState in componentDidUpdate for animations based on refs

Hi Stackoverflow community,

I'm doing some custom animations in my React app involving updating margins on a component with position: absolute . It's a menu that can toggle in and out.

I have a ref for the element it's toggling behind, whose node height I'm grabbing in componentDidMount . I use this height to know how far to move my toggling component.

I noticed when my app renders the first time my component isn't animating right because the height value is always zero. When I toggle it subsequently it works because the componentDidMount fires and updates the height of the other node properly.

To fix this I moved my divHeight field into the state and started calling setState in componentDidMount , now my toggleable component renders correctly each time.

Is this an anti-pattern? I can't see how else I would update my UI based on physical attributes of the HTML nodes, since those are only available through refs in componentDidMount ...

There is another method to perform physical changes in html elements instead of using refs. Instead you can toggle classes on and off elements to do what you want, like toggling a menu in and out of frame.

Below is an example of how its done without the use of refs. Click the button and you can imagine the red div is your top navigation menu.

 class MenuExample extends React.Component { constructor(props) { super(props); this.onToggleMenu = this.onToggleMenu.bind(this); this.state = { menuToggle: false }; } onToggleMenu(e) { this.setState({ menuToggle: !this.state.menuToggle }); } render() { return ( <div> <button onClick={this.onToggleMenu}>Open menu</button> <div className={`menu ${this.state.menuToggle && 'active'}`} /> </div> ); } } // Render it ReactDOM.render( <MenuExample/>, document.getElementById("react") ); 
 button { position: absolute; top: 150px; } .menu { position: absolute; top: -100px; left: 0px; width: 100%; height: 100px; background-color: red; transition: all .3s ease-in; -webkit-transition: all .3s ease-in; } .menu.active { top: 0px; } 
 <div id="react"></div> <script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react.min.js"></script> <script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react-dom.min.js"></script> 

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM