[英]How to update classNames in React properly?
On scroll down I have added and removed certain classes.向下滚动时,我添加和删除了某些类。 I want to revert the classes back on scroll up.
我想在向上滚动时恢复课程。 How can it be done using only ReactJS?
如何仅使用 ReactJS 来完成?
I have used the event listener to change the class.我已经使用事件侦听器来更改类。
The main concept is the content of the navbar should be displayed in the center, when we scroll down the website name which is displayed in a div should be displayed on the navbar and the content which is placed in the middle, should shift to the left and the div which displays the website name should disappear.主要概念是导航栏的内容应该显示在中心,当我们向下滚动时,显示在div中的网站名称应该显示在导航栏上,放置在中间的内容应该向左移动并且显示网站名称的 div 应该消失。 And when we scroll back up to the div with the website name, everything should come back to the same as it was before scrolling down.
当我们向上滚动到带有网站名称的 div 时,一切都应该恢复到向下滚动之前的状态。
import React, { Component } from 'react';
import '../Styles/Navbar.css';
export class Navbar extends Component {
handleScrollToElement(event) {
let linkPosition = document.querySelector('.collapse');
let brandName = document.querySelector('.navbar-brand');
if (window.pageYOffset > 250){
linkPosition.classList.remove('justify-content-center');
linkPosition.classList.add('justify-content-end');
brandName.classList.remove('invisible');
brandName.classList.add('visible');
}
}
componentDidMount() {
window.addEventListener('scroll', this.handleScrollToElement);
}
componentWillUnmount() {
window.removeEventListener('scroll', this.handleScrollToElement);
}
render() {
return (
<div>
<nav className='navbar navbar-expand-sm bg-dark navbar-dark fixed-top'>
<a className='navbar-brand invisible' href='#'>Website Name</a>
<button className='navbar-toggler' type='button' data-toggle='collapse' data-target='#navbarSupportedContent' aria-controls='navbarSupportedContent' aria-expanded='false' aria-label='Toggle navigation'>
<span className='navbar-toggler-icon'></span>
</button>
<div className='collapse navbar-collapse justify-content-center' id='navbarSupportedContent'>
<ul className='navbar-nav'>
<li className='nav-item active'>
<a className='nav-link' href='#'>Home</a>
</li>
<li className='nav-item'>
<a className='nav-link' href='#'>Item 2</a>
</li>
<li className='nav-item'>
<a className='nav-link' href='#'>About Us</a>
</li>
<li className='nav-item'>
<a className='nav-link' href='#'>Contact</a>
</li>
</ul>
</div>
</nav>
<div className='container-fluid hpage'>
<div className='inner'>
<h1 className='htext' >WEBSITE TITLE</h1>
</div>
</div>
</div>
)
}
}
export default Navbar;
When you use React.js, you should avoid direct DOM manipulation as much as possible.使用 React.js 时,应尽量避免直接操作 DOM。 If you really need a reference to a DOM, you should use ref instead.
如果您确实需要对 DOM 的引用,则应改用ref 。
I would set classNames
for linkPosition
and brandName
as state in constructor
and update them in handleScrollToElement
.我会设置
classNames
为linkPosition
和brandName
在状态constructor
和更新它们handleScrollToElement
。
Whenever those state
variables are changed, the render
function will be called and will update the view.每当更改这些
state
变量时,将调用render
函数并更新视图。
Since scroll
event fires a lot in short amount of time, I was worried about the performance issue as well.由于
scroll
事件在短时间内触发了很多,我也担心性能问题。 So I added shouldComponentUpdate in the code to prevent re-rendering the unchanged view.所以我在代码中添加了shouldComponentUpdate以防止重新渲染未更改的视图。
You can also consider to debounce the scroll event handler function to be called to reduce the amount of calling the setState
.您也可以考虑对要调用的滚动事件处理函数进行 debounce,以减少调用
setState
。
import React, { Component } from 'react';
import '../Styles/Navbar.css';
export class Navbar extends Component {
constructor(props) {
super(props);
this.state = {
linkPositionClassName: 'justify-content-center',
brandNameClassName: 'invisible',
};
}
handleScrollToElement(event) {
if (window.pageYOffset > 250){
this.setState({
linkPositionClassName: 'justify-content-end',
brandNameClassName: 'visible',
});
} else {
this.setState({
linkPositionClassName: 'justify-content-center',
brandNameClassName: 'invisible',
});
}
}
shouldComponentUpdate(nextProps, nextState) {
const { linkPositionClassName, brandNameClassName } = this.state;
// component needs to re-render only when at least one of the state changes
return nextState.linkPositionClassName !== linkPositionClassName || nextState.brandNameClassName !== brandNameClassName;
}
componentDidMount() {
window.addEventListener('scroll', this.handleScrollToElement);
}
componentWillUnmount() {
window.removeEventListener('scroll', this.handleScrollToElement);
}
render() {
return (
<div>
<nav className='navbar navbar-expand-sm bg-dark navbar-dark fixed-top'>
<a className=`navbar-brand ${this.state.brandNameClassName}` href='#'>Website Name</a>
<button className='navbar-toggler' type='button' data-toggle='collapse' data-target='#navbarSupportedContent' aria-controls='navbarSupportedContent' aria-expanded='false' aria-label='Toggle navigation'>
<span className='navbar-toggler-icon'></span>
</button>
<div className=`collapse navbar-collapse ${this.state.linkPositionClassName}` id='navbarSupportedContent'>
<ul className='navbar-nav'>
<li className='nav-item active'>
<a className='nav-link' href='#'>Home</a>
</li>
<li className='nav-item'>
<a className='nav-link' href='#'>Item 2</a>
</li>
<li className='nav-item'>
<a className='nav-link' href='#'>About Us</a>
</li>
<li className='nav-item'>
<a className='nav-link' href='#'>Contact</a>
</li>
</ul>
</div>
</nav>
<div className='container-fluid hpage'>
<div className='inner'>
<h1 className='htext' >WEBSITE TITLE</h1>
</div>
</div>
</div>
)
}
}
export default Navbar;
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.