ReactJS使状态变为

时间:2019-02-12 22:03:19

标签: javascript reactjs

我有:

export default class List extends Component {
...
render() {
        return <div>
...
<DropdownMenu text="Only show" isOpen={this.state.activeDropdown === "Only_show"} onClick={() => this.setState({ activeDropdown: "Only_show"})} inMenu={this.state.mouseInDropdown} onMouseEnter={() => this.setState({ mouseInDropdown: true })} onMouseLeave={() => this.setState({ mouseInDropdown: false })}>
                        <li>New</li>
                        <li>Old</li>
                    </DropdownMenu>
...
</div>

DropdownMenu.js

import React, {Component} from 'react';
import onClickOutside from 'react-onclickoutside'

class DropdownMenu extends Component {

    constructor(props) {
        super(props)

        this.state = {
            menuOpen: this.props.isOpen,
            highlight: false,
            count: this.props.count | 0,
            selection: null
        }
        this.showDropdown = this.showDropdown.bind(this);
        this.selectItem = this.selectItem.bind(this);

        this.menuIsOpen = false;

    }

    handleClickOutside = () => {
        console.log('in menu:'+this.props.inMenu)
        if(!this.props.inMenu) {
            console.log('onClickOutside() method called')
        }
    }

    showDropdown() {
        if(this.props.children) {
            this.setState({
                menuOpen: !this.state.menuOpen
            });
        }
    }

    selectItem(e) {
        console.log(e.target.textContent);
    }

    render() {
        console.log(this.props.inMenu)
        return <div className="dropdown__menu" onClick={this.props.onClick}>
            {this.props.text} {this.state.count > 0 ? <b>{this.state.count}</b> : ''}
            <div className="dropdown__content" style={this.props.isOpen ? {'display': 'block'} : {'display': 'none'}} onMouseEnter={this.props.onMouseEnter} onMouseLeave={this.props.onMouseLeave}>
                {this.props.children}
            </div>
        </div>
    }
}

export default onClickOutside(DropdownMenu)

我很难让this.props.isOpen成为this.state.isOpen,以便可以在handleClickOutside中使用它。 另一个问题是好像多次被调用,我的控制台显示如下: Console

如何解决这些问题?

作为参考,这里是我正在使用的“外部点击”:Click Outside

2 个答案:

答案 0 :(得分:0)

您的渲染功能正在查看this.props,而不是this.state

在我看来,这应该可行(并且我简化了代码):

<div className="dropdown__content" 
     style={{'display': this.state.menuOpen ? 'block' : 'none'}} 
     onMouseEnter={this.props.onMouseEnter} 
     onMouseLeave={this.props.onMouseLeave} >

    {this.props.children}
</div>

答案 1 :(得分:0)

正在发生的事情是您没有跟踪道具更改,即,当道具更改时,他们没有更新状态。您可以执行以下操作:

componentWillReceiveProps() {
   this.setState({ menuOpen: this.props.isOpen })
}

但是,在测试中,我发现其他一些令我难以置信的事情使这变得比原本需要的困难。因此,这是工作代码的新答案(无需跟踪道具)。

我看不到(基于您所发布的内容)为什么List组件需要跟踪菜单状态和鼠标位置,因此我将两者都移到了DropdownMenu组件本身。您仍然可以将打开/关闭的默认值作为“ isOpen”道具传递。

List.js

import React, {Component} from 'react';
import DropdownMenu from './DropdownMenu'

export default class List extends Component {
    render() {
        return <div>
                <DropdownMenu text="Only show" isOpen={false} >
                            <li>New</li>
                            <li>Old</li>
                </DropdownMenu>
                </div>
    }
}

我将showDropdown更改为toggleDropdown,因为这是对其操作的更准确描述。鼠标位置移到了父div,我将selectItem连接到了包含子项的div。

DropdownMenu.js

import React, {Component} from 'react';
import onClickOutside from 'react-onclickoutside'

class DropdownMenu extends Component {

    constructor(props) {
        super(props)

        this.state = {
            menuOpen: props.isOpen,
            highlight: false,
            count: props.count || 0,
            selection: null,
            mouseInDropdown: false,
        }
        this.toggleDropdown = this.toggleDropdown.bind(this);
        this.selectItem = this.selectItem.bind(this);
    }

    handleClickOutside = () => {
        if(!this.state.mouseInDropdown) {
            // close it no matter what its state is
            this.setState({menuOpen: false}) 
        }
    }

    toggleDropdown() {     
        if(this.props.children) {
            this.setState({
                menuOpen: !this.state.menuOpen
            });
        }
    }

    selectItem(e) {
        console.log(e.target.textContent);
    }

    render() {        
        //console.log("Render inMenu: " + this.state.mouseInDropdown)
        return <div className="dropdown__menu"
                    onClick={this.toggleDropdown}                     
                    onMouseEnter={() => this.setState({ mouseInDropdown: true })} 
                    onMouseLeave={() => this.setState({ mouseInDropdown: false })}> 

            {this.props.text} {this.state.count > 0 ? <b>{this.state.count}</b> : ''}

            <div className="dropdown__content" 
                style={{'display': this.state.menuOpen ? 'block' : 'none'}}
                onClick={this.selectItem} 
            >
                {this.props.children}
            </div>
        </div>
    }
}

export default onClickOutside(DropdownMenu)