【问题标题】:React modal with delete functionality具有删除功能的反应模式
【发布时间】:2018-03-31 23:20:53
【问题描述】:

我有一个应用程序,它显示行中的项目列表。每个项目都有一个相应的删除按钮。当我单击它时,它会显示一个带有确认的模式。当我单击“取消”时,该操作被取消。当我单击“确认”时,模式如下:
1. 它显示一个加载图标
2. 它改变了样式(颜色和文字 - 现在它说它完成了)
3.它删除项目

到目前为止,我得到的只是显示模式,与本文相同:
https://daveceddia.com/open-modal-in-react/
加上单击确认时的控制台日志记录。
如何实现该功能?
我需要使用 Redux 吗?或者是否有某种用于确认对话框的库?

我的代码: https://codesandbox.io/s/6n03myqw8w

【问题讨论】:

  • 不,你不需要 redux,你可以有一个函数,当你在模态确认上点击 OK 时,它会删除记录。
  • 我在想这样的事情:approveModal = () => { console.log('deleting'); // load icon, then change modal style, then delete item }; 但是如何实现呢?
  • @n3stle 你能发布你的代码吗?
  • @n3stle 发布您的代码,最好在codesandbox.io/s/new
  • 已经在帖子中,将在代码和框中做同样的事情

标签: javascript reactjs redux react-redux frontend


【解决方案1】:

我需要使用 Redux 吗?

不,绝对不是

如何实现该功能? [...] 或者是否有某种用于确认对话框的库?

听起来你已经在那里了。而不是console.log()确认,做这件事!我所说的“那个东西”指的是类似这样的东西......

handleConfirm = () => {
  this.setState({loading: true}); // show loading icon
  deleteItem(id)
    .then(() => {
      this.setState({
        loading: false, // hide loading icon
        success: true, // show colored success text
      });
    }
    .catch((err) => {
      // handle delete error here
    }

}

你的渲染函数看起来像这样......

render() {
  const { loading, success } = this.state;
  return (
    {loading && <Loading />}
    {success && <SuccessMessage />}
    {!loading && !success && <ConfirmMessageWithButtons />}
  )
}

更新:我看到您现在已经在代码沙箱上提供了代码,所以这里有一个使用您的代码的笨拙的解决方案。它很笨拙,因为它使用 setTimeouts 模拟异步操作

import React, { Component } from 'react';
import ReactDOM from 'react-dom';
import Modal from './components/Modal';

class App extends Component {
  constructor(props) {
    super(props);

    this.state = { 
      isOpen: false,
      loading: false,
      success: false, 
    };
  }

  toggleModal = () => {
    this.setState({
      isOpen: !this.state.isOpen,
    });
  };

  approveModal = () => {
    this.setState({loading: true });
    setTimeout(() => this.setState({ 
      loading: false,
      success: true 
    }), 1000)
    setTimeout(() => this.setState({ 
      isOpen: false 
    }), 3000)
  };

  render() {
    const { loading, success } = this.state;
    return (
      <div className="App">
        {!success && !loading && <p>Item to delete</p>}
        <button onClick={this.toggleModal}>Delete</button>

        <Modal show={this.state.isOpen} onApprove={this.approveModal} onClose={this.toggleModal}>
          {loading && "Loading..."}
          {success && "Success (make me green)"}
          {!success && !loading && "Here's some text for the modal"}
        </Modal>
      </div>
    );
  }
}
ReactDOM.render(<App />, document.getElementById('root'));

这是一个链接https://codesandbox.io/s/10o12zzk63

【讨论】:

    【解决方案2】:

    这是一个不使用 Redux 的示例。它展示了如何使用组件来解决必须依赖数据存储的问题。主容器保存数据和动作,我们只需传递这些动作和必要的数据即可删除和显示模式。

    现在这不考虑加载和样式更改,但您可以将它们绑定到 MockModal 类中的操作以添加假加载图标(因为我们使用来自容器的数据,所以数据是即时的)。样式更改可以添加到 MockModal 中的 removeTask 方法中,或者您可以研究一种动画技术来增强 UI。以下纯属函数式实现。

    如果您需要更多帮助,请告诉我。

    class MockModal extends React.Component {
      removeTask = () => this.props.removeTask(this.props.data);
      closeModal = () => this.props.closeModal();
      render() {
        const { id, name } = this.props.data;
        if (this.props.displayModal) {
          return (
            <div>
              <h5>You want to delete task {id} : {name}</h5>
              <button onClick={this.removeTask}>Confirm</button>
              <button onClick={this.closeModal}>Close</button>
            </div>
          )
        }
        return null;
      }
    }
    
    class Task extends React.Component {
      showModal = (task) => this.props.show(this.props.task);
      render() {
        const { id, name } = this.props.task;
        return (
          <div>
            <h5>{id}:{name}</h5>
            <button onClick={this.showModal}>(REMOVE)</button>
          </div>
        )
      }
    }
    
    class App extends React.Component {
      state = {
        showModal: false,
        modal: {
          id: null,
          name: null,
        },
        tasks: [
          { id: 1, name: 'Star Wars' },
          { id: 2, name: 'Harry Potter' },
          { id: 3, name: 'Lord of the Rings' },
        ],
      }
      showModal = (task) => this.setState({ modal: task, showModal: true, });
      hideModal = () => this.setState({ showModal: false, });
      removeTask = (activeTask) => {
        const index = this.state.tasks.findIndex(task => {
          return task.id === activeTask.id;
        });
        this.setState({
          showModal: false,
          tasks: [
            ...this.state.tasks.slice(0, index),
            ...this.state.tasks.slice(index + 1),
          ]
        })
      }
      render(){
        return (
          <div>
            <MockModal 
              displayModal={this.state.showModal}
              closeModal={this.hideModal}          
              removeTask={this.removeTask}
              data={this.state.modal} 
            />
            {this.state.tasks.map(task => {
              return (
                <Task key={task.id} task={task} show={this.showModal} />
              )
            })}
          </div>
        )
      }
    }
    
    ReactDOM.render(<App />, document.getElementById('root'));
    <script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react.min.js"></script>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react-dom.min.js"></script>
    <div id="root"></div>

    【讨论】:

    • 您的应用程序中存在错误。如果您先删除第二个项目,它也会删除第三个项目。
    • @Win 是的,有一个错误,你能帮我修复它吗?我尝试用slice 做一些事情,但无济于事
    • @n3stle 抱歉,我输入的是 splice 而不是 slice。全部固定。
    猜你喜欢
    • 1970-01-01
    • 2015-06-07
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-12-23
    • 2020-03-10
    • 2019-04-30
    • 2019-11-21
    相关资源
    最近更新 更多