我正在使用一个项目,我有一个菜单按钮。
<a ref="btn" href="#" className="btn-menu show-on-small"><i></i></a>
Sidenav组件如:
<Sidenav ref="menu" />
我编写了以下代码来切换菜单:
class Header extends React.Component {
constructor(props){
super(props);
this.toggleSidenav = this.toggleSidenav.bind(this);
}
render() {
return (
<div className="header">
<i className="border hide-on-small-and-down"></i>
<div className="container">
<a ref="btn" href="#" className="btn-menu show-on-small"><i></i></a>
<Menu className="menu hide-on-small-and-down"/>
<Sidenav />
</div>
</div>
)
}
toggleSidenav() {
this.refs.btn.classList.toggle('btn-menu-open');
}
componentDidMount() {
this.refs.btn.addEventListener('click', this.toggleSidenav);
}
componentWillUnmount() {
this.refs.btn.removeEventListener('click', this.toggleSidenav);
}
}
问题是this.refs.sidenav
不是DOM元素,我不能在他身上添加一个类。
有人可以解释一下如何切换Sidenav
组件上的课程,就像我在按钮上一样吗?
答案 0 :(得分:21)
如果希望React正确有效地呈现DOM,则必须使用组件的State来更新组件参数,例如Class Name。
更新:我更新了示例以点击按钮切换Sidemenu。这不是必需的,但你可以看到它是如何工作的。您可能需要使用“this.state”与“this.props”,如我所示。我习惯使用Redux组件。
constructor(props){
super(props);
}
getInitialState(){
return {"showHideSidenav":"hidden"};
}
render() {
return (
<div className="header">
<i className="border hide-on-small-and-down"></i>
<div className="container">
<a ref="btn" onClick={this.toggleSidenav.bind(this)} href="#" className="btn-menu show-on-small"><i></i></a>
<Menu className="menu hide-on-small-and-down"/>
<Sidenav className={this.props.showHideSidenav}/>
</div>
</div>
)
}
toggleSidenav() {
var css = (this.props.showHideSidenav === "hidden") ? "show" : "hidden";
this.setState({"showHideSidenav":css});
}
现在,当您切换状态时,组件将更新并更改sidenav组件的类名。您可以使用CSS来显示/隐藏使用类名称的sidenav。
.hidden {
display:none;
}
.show{
display:block;
}
答案 1 :(得分:11)
refs
不是DOM元素。为了找到DOM元素,您需要先使用findDOMNode
menthod。
做,这个
var node = ReactDOM.findDOMNode(this.refs.btn);
node.classList.toggle('btn-menu-open');
或者,您可以像这样使用(几乎是实际代码)
this.state.styleCondition = false;
<a ref="btn" href="#" className={styleCondition ? "btn-menu show-on-small" : ""}><i></i></a>
然后,您可以根据州的状态变化条件更改styleCondition
。
答案 2 :(得分:3)
Ori Drori的评论是正确的,你不是这样做的“React Way”。在React中,理想情况下,您不应该使用DOM更改类和事件处理程序。在React组件的render()方法中执行;在这种情况下,这将是sideNav和你的标题。如何在代码中完成此操作的粗略示例如下。
HEADER
class Header extends React.Component {
constructor(props){
super(props);
}
render() {
return (
<div className="header">
<i className="border hide-on-small-and-down"></i>
<div className="container">
<a ref="btn" href="#" className="btn-menu show-on-small"
onClick=this.showNav><i></i></a>
<Menu className="menu hide-on-small-and-down"/>
<Sidenav ref="sideNav"/>
</div>
</div>
)
}
showNav() {
this.refs.sideNav.show();
}
}
SIDENAV
class SideNav extends React.Component {
constructor(props) {
super(props);
this.state = {
open: false
}
}
render() {
if (this.state.open) {
return (
<div className = "sideNav">
This is a sidenav
</div>
)
} else {
return null;
}
}
show() {
this.setState({
open: true
})
}
}
你可以在这里看到我们不是在切换类,而是使用组件的状态来渲染SideNav。这种方式或类似方式是使用反应的整个前提。如果您使用的是bootstrap,那么有一个库将引导元素与反应方式集成在一起,允许您使用相同的元素,但在它们上设置状态而不是直接操作DOM。它可以在这里找到 - https://react-bootstrap.github.io/
希望这有帮助,并享受使用React!
答案 3 :(得分:2)
首先,您应该创建构造函数 像这样
constructor(props) {
super(props);
this.state = {
close: true,
};
}
yourFunction = () => {
this.setState({
close: !this.state.close,
});
};
然后像这样使用
render() {
const {close} = this.state;
return (
<Fragment>
<div onClick={() => this.yourFunction()}></div>
<div className={close ? "isYourDefaultClass" : "isYourOnChangeClass"}></div>
</Fragment>
)
}
}
请提供更好的解决方案
答案 4 :(得分:0)
对于任何在2019年阅读此书的人,在发布React 16.8之后,请查看React Hooks。它确实简化了组件中的处理状态。这些文档写得很好,并附带了您所需要的示例。