使用React如何从容器组件切换嵌套组件的可见性?

时间:2016-12-09 14:28:23

标签: javascript reactjs redux

目标

我正在尝试根据Google Material Design layout模仿 React Redux 中的列表控制组件。

列表控件将允许您在列表中创建重命名删除项目,而无需导航到新页面。

重命名删除列表项的操作将显示在单击每个列表项上的链接触发的弹出菜单组件

当前组件结构

我有一个顶级容器组件 ListItemPage 链接到Redux我用来维护列表的状态,然后我将更改推送到商店。

ListItemPage 中,我正在呈现项目列表,每个项目都有一个唯一的菜单组件

ListItemPage组件

class ListItemPage extends Component {
    constructor(props, context) {
        super(props, context);
    }

    onMenuClick(){}
    onRename(){}
    onDelete(){}

    render () {
        const { listItems } = this.props;

        return(
            <div>
                <ul>
                    {
                        listItems.map(listItem =>
                            <li>
                                <a href={`/items/${listItem.id}`}>
                                    {listItem.title}
                                </a>
                                <a href="#" onClick={onMenuClick}>
                                    <i className="material-icons">more_vert</i>
                                </a>
                                <Menu
                                    showMenu={showMenu}
                                    onRename={onRename}
                                    onDelete={onDelete}/>
                            </li>
                        )
                    }
                <ul>
                <a href="#" onClick={null}>
                    <i className="material-icons">add</i>
                </a>
            </div>
        );
    }
}

function mapStateToProps(state, ownProps){
    return {
        listItems: state.listItems
    }
}

function mapDispatchToProps(dispatch) {
  return {
    actions: bindActionCreators(listItemActions, dispatch)
  };
}

export default connect(mapStateToProps, mapDispatchToProps)(ListItemPage);

菜单组件

const Menu = (showMenu, onDelete, onRename) => {
    if(showMenu) {
        return(
            <nav>
                <a href="#" onDelete={onDelete}>Delete</a>
                <a href="#" onRename={onRename}>Rename</a>
            </nav>
        );
    }

    return null;
}

export default Menu;

Redux商店数据结构

let listItems = [
    { id: 1, title: 'Item A' },
    { id: 2, title: 'Item B' },
    { id: 3, title: 'Item C' }
];

问题

我无法弄清楚如何根据列表项 onClickEvent 显示和隐藏独特的菜单组件。

我在考虑如何为一个非强制性项目 showMenu 传递一个bool,但我不确定在哪里为每个项目定义这个,或者即使这是最好的方法。

我知道我可以使用参考来达到这个目的但我不希望建议只使用Refs作为最后的手段。

1 个答案:

答案 0 :(得分:3)

伟大的第一篇文章!很好地呼吁限制使用refs

一种方法可能是在ListItemPage组件中保留当前显示哪个菜单的状态。

constructor(props, context) {
    super(props, context);
    this.state = { showMenu: null };
}

然后,在您的onMenuClick函数中,接收项目的ID以显示菜单,并分配给州。

onMenuClick(id) {
  this.setState({ showMenu: id });
}

这将按如下方式传递到您的菜单。

showMenu={this.state.showMenu === listItem.id}

关闭菜单只需要将this.state.showMenu的值重置为null

这假设在给定时间只显示一个菜单。如果那不是真的,请告诉我,我会更新。