切换按钮无法正确更新状态

时间:2019-10-07 13:10:28

标签: reactjs sidebar

我有一个按钮,用于在React应用程序中切换边栏。切换按钮对于前两个切换状态工作正常,而不是第三次重复该状态两次。 这就是我将状态从子组件切换到父组件的方式:

import React, { Component } from 'react'

export default class Header extends Component {
    constructor(props) {
        super(props)

        this.state = {
             toggle: false
        }
    }

    toggleSidebar = () => {

        this.setState({
            toggle : !this.state.toggle
        });
        console.log(this.state.toggle)
        this.props.getToggleState(this.state.toggle);
    }

    render() {
        return (
            <div>
                 <button style={{width: '60px'}} onClick={this.toggleSidebar}>Toogle</button>
            </div>
        )
    }
}



export default class App extends Component{

  constructor(props) {
    super(props)

    this.state = {
      toggleVal:''
    }
  }

  getData = (val) => {
   this.setState({
     toggleVal: val
   })
}

  render(){
    let toggleConst = '';
    if(this.state.toggleVal){
      toggleConst = (
                <Router>
                <div style={{display: 'flex', backgroundColor: '#ccc', height: '100%', flexDirection:'row'}}>
                  <div style={{flexDirection:'column'}}>
                    <Header getToggleState={this.getData}/>
                      <Routes/>
                    <Footer/>
                  </div>
                </div>
              </Router>
      )
    }
    else{
      toggleConst = (
                <Router>
                <div style={{display: 'flex', backgroundColor: '#ccc', height: '100%', flexDirection:'row'}}>
                  <SideNav toggleVal={this.state.toggleVal}/>
                  <div style={{flexDirection:'column'}}>
                    <Header getToggleState={this.getData}/>
                      <Routes/>
                    <Footer/>
                  </div>

                </div>
              </Router>
      )
    }
    return (
      toggleConst
    );
  }

}

切换按钮可以完美地隐藏/打开侧栏,但是当两次出现“ false”时,它会停留在状态上。 状态控制台的运行方式如下:

enter image description here

我在这里找不到问题。任何帮助表示赞赏。

4 个答案:

答案 0 :(得分:1)

  

App.js

import React, {Component} from 'react';
import { BrowserRouter as Router} from "react-router-dom";
import Header from './Header';
import Sidebar from './Sidebar'

export default class App extends Component{

  constructor(props) {
    super(props)

    this.state = {
      toggleVal: false
    }
  }

  getData = (val) => {

   this.setState({
     toggleVal: val
   });
}

  render(){
    console.log("called.....123...",this.state.toggleVal)
    if(this.state.toggleVal){
      return (
                <Router>
                <div style={{display: 'flex', backgroundColor: '#ccc', height: '100%', flexDirection:'row'}}>
                <Sidebar toggleVal={this.state.toggleVal}/>
                  <div style={{flexDirection:'column'}}>
                    <Header getToggleState={this.getData} />
                  </div>
                </div>
              </Router>
      )
    }
    else{
      return (
                <Router>
                <div style={{display: 'flex', backgroundColor: '#ccc', height: '100%', flexDirection:'row'}}>
                  <Sidebar toggleVal={this.state.toggleVal}/>
                  <div style={{flexDirection:'column'}}>
                    <Header getToggleState={this.getData}/>

                  </div>
                </div>
              </Router>
      )
    }
  }

}
  

Header.js

import React, { Component } from 'react'

export default class Header extends Component {
    constructor(props) {
        super(props)

        this.state = {
             toggle: false
        }
    }


    toggleSidebar = () => {

        this.setState({
          toggle: !this.state.toggle
        },()=>{
            // console.log(this.state.toggle)
            this.props.getToggleState(this.state.toggle);
        });

    }

    render() {
        return (
            <div>
                 <button onClick={()=>this.toggleSidebar(this.state.toggle)}>Toogle</button>
            </div>
        )
    }
}
  

Sidebar.js

import React, { Component } from 'react'
import { NavLink } from "react-router-dom";


export default class Sidebar extends Component {
    render() {
        return (
            <>
            {
                this.props.toggleVal &&
                    <div className="sidebar_container">
                        <nav className="nav_container">
                            <ul>
                                <li>
                                    <NavLink to="/" activeClassName="active" exact={true}>Dashboard</NavLink>
                                </li>
                                <li>
                                    <NavLink to="/user" activeClassName="active">User PRofile</NavLink>
                                </li>
                                <li>
                                    <NavLink to="/register" activeClassName="active">Register</NavLink>
                                </li>
                            </ul>
                        </nav>
                    </div>
            }
            </>
        )
    }
}

https://repl.it/repls/IncredibleLinedCgi

这将为您工作

答案 1 :(得分:0)

更改部分代码:

this.setState({
        toggle : !this.state.toggle
    });

对此:

this.setState(prev => {
        return { toggle : !prev.toggle }
    });

答案 2 :(得分:0)

您应该在setState回调中调用getToggleState,以便使用正确的状态作为参数

this.setState(prevState => {
  this.props.getToggleState(!prevState.toggle);
  return { toggle: !prevState.toggle };
});

尽管采用了这种解决方案,最好不要在子组件<Header />中保留重复状态,因为条件渲染是“父职责”。<​​/ p>

答案 3 :(得分:0)

在我看来,这可能要简单得多。

  
      
  1. 在父组件应用ìsToggled上定义状态
  2.   
  3. 通过回调this.props.onToggle()从子组件标头进行调用
  4.   
  5. 在父组件{this.state.isToggled && <Sidebar/>}上使用条件渲染
  6.   
import React, {Component} from 'react';
import {BrowserRouter as Router} from "react-router-dom";
import Header from './Header';
import Sidebar from './Sidebar'

export default class App extends Component {
    constructor(props) {
        super(props);
        this.state = {
            isToggled: false
        }
    };

    onToggle = () => {
        this.setState({
            isToggled: !this.state.isToggled
        });
        console.log(this.state.isToggled);
    };

    render() {
        return (
            <Router>
                <div style={{display: 'flex', backgroundColor: '#ccc', height: '100%', flexDirection: 'row'}}>
                    <div style={{flexDirection: 'column'}}>
                        <Header onToggle={this.onToggle}/>
                    </div>
                    {this.state.isToggled && <Sidebar/>}
                </div>
            </Router>
        )
    }
}
import React, {Component} from 'react'

export default class Header extends Component {
    constructor(props) {
        super(props)
    }

    render() {
        return (
            <div>
                <button onClick={() => {
                    this.props.onToggle()
                }}>Toggle
                </button>
            </div>
        )
    }
}
import React, {Component} from 'react'
import {NavLink} from "react-router-dom";

export default class Sidebar extends Component {
    render() {
        return (
            <div className="sidebar_container">
                <nav className="nav_container">
                    <ul>
                        <li>
                            <NavLink to="/" activeClassName="active" exact={true}>Dashboard</NavLink>
                        </li>
                        <li>
                            <NavLink to="/user" activeClassName="active">User PRofile</NavLink>
                        </li>
                        <li>
                            <NavLink to="/register" activeClassName="active">Register</NavLink>
                        </li>
                    </ul>
                </nav>
            </div>
        )
    }
}