反应阻止切换多个模态

时间:2017-09-22 21:20:06

标签: reactjs redux

我的反应应用程序有问题。我已经生成了100个项目的列表。我使用map函数

显示列表中的每个元素
<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>

我的项目视图显示名称,年龄和实力。在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中的另一个按钮后,打开的模态将被关闭,合适的将打开。

现在发生的事情是我可以打开多个模态并且每个思考都有效,但我想在页面上显示一个模态。

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

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

Visualization what i want to do

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

1 个答案:

答案 0 :(得分:2)

以下是我重构代码的方法:

  • 将ItemView类组件降级为container / dump-componentsnet。请记住,您拥有的类组件越少越好。
  • 点击该按钮后,我将存储点击currentItemId
  • 中当前项目的ID
  • 然后我只在状态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'));