【问题标题】:React prevent from toggle multiple modals反应防止切换多个模式
【发布时间】:2017-09-22 21:20:05
【问题描述】:

我的 react 应用有问题。我已经生成了 100 个项目的列表。我使用地图功能显示列表中的每个元素

<ul className="list">
    {this.props.items.map((item) => {
      return (
        <ItemView
          key={item.id}
          id={item.id}
          name={item.name}
          strenght={item.strenght}
          age={item.age}
        />
      );
    })}
</ul>

我的项目视图显示名称、年龄和强度。 on mouseEnter 显示按钮,点击后在被点击的元素下显示模态。

class ItemView extends React.Component {
  constructor(props) {
    super(props);
    this.state = {
      isMouseInside: false,
      isModalOpen: false,
    };
  }

  mouseEnter = () => {
    this.setState({ isMouseInside: true });
  };

  mouseExit = () => {
    this.setState({ isMouseInside: false });
  };

  showModal = () => {
    this.setState({ isModalOpen: !this.state.isModalOpen });
  };

  closeModal = () => {
    this.setState({ isModalOpen: false });
  };

  render() {
    return (
      <li
        onMouseEnter={this.mouseEnter}
        onMouseMove={this.mouseEnter}
        onMouseLeave={this.mouseExit}
      >
        <div className="item__row">
           <h5>{this.props.name}</h5>
           <h6>Age: {this.props.age}</h6>
           <p>{this.props.strenght}/100</p>

          {this.state.isMouseInside ? (
            <button className="btn" onClick={() => this.showForm(false)}>
              Change data
            </button>
          ) : null}

        </div>
        {this.state.isModalOpen ? (
          <Modal
            onSubmit={this.handleSubmitForm}
          />
        ) : null}
      </li>
    );
  }
}

我想要做的是防止阻止打开两个模态的可能性,甚至更好的是,如果单击另一个 itemView 中的另一个按钮后,打开的模态将被关闭并且合适的会打开。

现在发生的事情是我可以打开多个模态并且everythink 工作,但我想让一个模态显示在页面上。

我尝试在 showModal 函数中的 this.setState({ isModalOpen: !this.state.isModalOpen }) 之前创建另一个函数 closeModal 将 isModalOpen 的状态设置为 false,但它不起作用。

在这个应用程序中,我使用 redux,如果 redux 可以帮助解决问题,我可以使用它。

Visualization what i want to do

CODEPEN 示例:https://codepen.io/dominik3246/pen/QqKzzp

【问题讨论】:

  • 你能把你的代码放在codepen上吗?我们会更容易解决这个问题。
  • 一个类似的例子,但工作方式相同codepen.io/dominik3246/pen/QqKzzp
  • 好的,这很酷。只是为了澄清您的要求 - 您只需要打开一个模式。当打开一个模态并单击“更改数据”时,该模态将关闭并且与“更改数据”相关的模态将打开?
  • 是的,正是:)
  • 当您认为 stackoverflow 上的问题有正确答案时,您应该勾选“非常好”的标志以将其标记为您的答案。当有一个您认为对不属于您的问题有好处的答案时,您可以通过单击该问题旁边的向上箭头来投票。随着您在 SOF 上的进展,如果您认为答案无效或不符合 SOF 标准,您还将有权拒绝投票

标签: reactjs redux


【解决方案1】:

我是这样重构你的代码的:

  • 已将 ItemView 类组件降级为容器/转储组件。请记住,您拥有的类组件越少越好。
  • 单击按钮时,我将当前单击的项目的ID存储在currentItemId中
  • 然后我只显示状态currentItemId 与当前项目 ID 匹配

我已经尽力在重构中使用 React 的模式。事实上,我将 LOC 从 85 减少到 59,现在 IMO 的代码看起来更整洁了。

使用此代码作为参考,了解将来如何对您的 React 组件和容器进行编码,因为您的代码需要一些润色。

Codepen:https://codepen.io/metju/pen/LzRqJp

代码:

class List extends React.Component {
    constructor() {
        super()
        this.state = {
            currentItemId: undefined,
            data: [{id: 0, name: "item1", strenght: 5, age: 5}, {id: 1, name: "item2", strenght: 5, age: 5}, {
                id: 2,
                name: "item1",
                strenght: 5,
                age: 5
            }, {id: 3, name: "item1", strenght: 5, age: 5}, {id: 4, name: "item1", strenght: 5, age: 5}],
        };
        this.toggleModalFunc = this.toggleModalFunc.bind(this);
    }

    toggleModalFunc(id) {
        const currentItemId = id !== this.state.currentItemId ? id : undefined
        this.setState({ currentItemId })
    };

    render() {
        return (
            <ul className="list">
                {this.state.data.map((d) => {
                    return (
                        <ItemView
                            key={d.id}
                            name={d.name}
                            strenght={d.strenght}
                            age={d.age}
                        >
                            <button className="btn" itemId={d.id} onClick={() => this.toggleModalFunc(d.id)}>
                                Change data
                            </button>
                            {this.state.currentItemId === d.id ? <Modal /> : null}
                        </ItemView>
                    );
                })}
            </ul>
        );
    }
}
const Modal = () => (
    <div>
        THIS IS MODAL
    </div>
)
const ItemView = (props) => {
    return <li>
        <div className="item__row">
            <h5>{props.name}</h5>
            <h6>Age: {props.age}</h6>
            <p>{props.strenght}/100</p>
            {props.children[0]}
        </div>
        {props.children[1]}
    </li>
}

ReactDOM.render(<List />, document.getElementById('app'));

【讨论】:

  • 太好了,答案太棒了:D 我只有一个问题。在第二次点击时隐藏显示的模式很难吗?我的意思是如果显示模态,然后在第二次单击按钮时将其隐藏。查看没有任何显示模式的列表。
  • 要在第二次点击时隐藏模式,只需在 Matthew 的 toggleModalFunc 中添加一个条件。如果id === this.state.currentItemId,则将状态的currentItemId 设置为undefined。
  • 谢谢@jaxx。我测试了你的逻辑。有效。我现在已将其添加到我的答案中。
  • @Matthew 真的很喜欢您处理附加条件的方式,这让我希望我能再次支持您的答案,因为它是简洁优雅的解决方案的完美模型。赞一个!
猜你喜欢
  • 2020-10-20
  • 2013-02-25
  • 2019-07-26
  • 1970-01-01
  • 2022-01-21
  • 2021-01-03
  • 2020-10-20
  • 2020-06-21
  • 1970-01-01
相关资源
最近更新 更多