【问题标题】:In React, using bootstrap modal how to edit and update State?在 React 中,使用引导模式如何编辑和更新状态?
【发布时间】:2018-07-21 06:32:20
【问题描述】:

我有一个显示项目列表的表格。当我单击一行以呈现模态时,如何使用我单击的数据预填充我的输入字段,然后编辑这些字段以便可以使用我提供的新数据更新状态?

这是我的代码分解与各个文件:

Project.js

const Project = ({ companies, projects }) => {
    return(
        <div>
            <section id={styles.project} className="divider overlay-light" data-bg-img="http://placehold.it/1920x1280">
                <div className={`container ${styles.wrapper}`}>
                    <div className="row">
                        <div className={`col-md-12 ${styles['proj-header']}`}>
                            <h2 className="title">Projects</h2>
                            <button type="button" className={`btn ${styles['btn-project']}`} data-toggle="modal" data-target="#createProject">Create New Project</button>
                            {
                                companies.map((company, i) => {
                                    return <CreateProjectModal key={i} company={company} />
                                })
                            }
                        </div>
                    </div>
                    <ManageColumns />
                    <div className="row">
                        <div className="col-md-12">
                            <div className={`${styles['table-responsive']} ${styles['dashboard-overview']} tableContainer`}>
                                <table className={`table table-striped scrollTable`}>
                                    <thead className="fixedHeader">
                                        <tr>
                                            <th>Project Name <i className="fas fa-sort-amount-down"></i></th>
                                            <th>Project Description</th>
                                            <th>Action</th>
                                        </tr>
                                    </thead>
                                    <tbody className="scrollContent">
                                        {
                                            projects.map((project, i) => {
                                                return (
                                                        <tr key={i}>
                                                            <td>{project.project_name}</td>
                                                            <td>{project.description}</td>
                                                            <td>
                                                                <EditProjectModal projects={projects} />
                                                            </td>
                                                        </tr>
                                                    );
                                            })
                                        }
                                    </tbody>
                                </table>
                            </div>
                        </div>
                    </div>
                </div>
            </section>
        </div>
    )
}
export default Project;

CreateProjectModal.js

class CreateProjectModal extends Component {
  constructor(props) {
    super(props);
    this.state = {
      project_name: '',
      description: ''
    }
  }

  onProjectNameChange(event)  {  this.setState({ project_name: event.target.value });  }
  onDescriptionChange(event)  {  this.setState({ description: event.target.value });   }

  handleSubmit(company) {
    fetch(`http://localhost:5000/companys/${company._id['$oid']}/projects`, {
        method: 'POST',
        headers: {'Content-Type': 'application/json'},
        body: JSON.stringify({
          project: {
            project_name: this.state.project_name,
            description: this.state.description
          }
        })
      })
      .then(response => response.json())
      .then(data => { return data })
      .catch(err => console.log(err));
  }

    render() {
    const { company } = this.props;
    return(
      <div>
        <div id="createProject" className="modal fade" tabIndex="-1" role="dialog">
          <div className={`modal-dialog modal-lg ${styles['create-proj-modal']}`}>
            <div className="modal-content">
              <div className={`modal-header ${styles['create-proj-modal-header']}`}>
                <button type="button" className={`close ${styles.closeModal}`} data-dismiss="modal" aria-label="Close"><span aria-hidden="true">&times;</span></button>
                <h3 className="modal-title" id="myModalLabel2">Create New Project</h3>
              </div>
              <div className={`modal-body ${styles['proj-modal-body']}`}>
                <form>
                  <div className={`form-group ${styles.formGroup} ${styles.projName}`}>
                    <label htmlFor="project-name" className="col-form-label">Project Name</label>
                    <input type="text" className="form-control" id="project-name" name="project_name" onChange={(e) => onProjectNameChange(e, this.state)} />
                  </div>
                  <div className={`form-group ${styles.formGroup}`}>
                    <label htmlFor="description" className="col-form-label">Description</label>
                    <textarea className="form-control" id="description" rows="4" name="description" onChange={(e) => onDescriptionChange(e, this.state)} ></textarea>
                  </div>
                </form>
              </div>
              <div className={`modal-footer ${styles.modalFooter}`}>
                <button type="button" className={`btn btn-primary text-white ${styles.saveBtn}`} onClick={() => handleSubmit(company)}>Save Project</button>
                <button type="button" className={`btn btn-default ${styles.cancelBtn}`} data-dismiss="modal">Cancel</button>
              </div>
            </div>
          </div>
        </div>
      </div>
    )
  }
}

export default CreateProjectModal;

EditProjectModal.js

class EditProjectModal extends Component {  
  constructor(props) {
    super(props);
    this.state = {
      project_name: '',
      description: ''
    }
  }

  onProjectNameChange(event)  {  this.setState({ project_name: event.target.value });  }
  onDescriptionChange(event)  {  this.setState({ description: event.target.value });   }

  handleSubmit(project) {
    fetch(`http://localhost:5000/projects/${project._id['$oid']}`, {
        method: 'PUT',
        headers: {'Content-Type': 'application/json'},
        body: JSON.stringify({
          project: {
            project_name: this.state.project_name,
            description: this.state.description
          }
        })
      })
      .then(response => response.json())
      .then(data => { return data })
      .catch(err => console.log(err));
  }

  render() {
    const { project } = this.props;
    return(
      <div className="btn-group">
        <NavLink type="button" to="#" className={`${styles['pencil-link']}`} data-toggle="modal" data-target="#editProject">
          <i className={`fas fa-pencil-alt ${styles.pencil}`}></i>
        </NavLink>
        <div id="editProject" className="modal fade" tabIndex="-1" role="dialog">
          <div className={`modal-dialog modal-lg ${styles['create-proj-modal']}`}>
            <div className="modal-content">
              <div className={`modal-header ${styles['create-proj-modal-header']}`}>
                <button type="button" className={`close ${styles.closeModal}`} data-dismiss="modal" aria-label="Close"><span aria-hidden="true">&times;</span></button>
                <h3 className="modal-title" id="myModalLabel2">Edit Project</h3>
              </div>
              <div className={`modal-body ${styles['proj-modal-body']}`}>
                <form>
                  <div className={`form-group ${styles.formGroup} ${styles.projName}`}>
                    <label htmlFor="project-name" className="col-form-label">Project Name</label>
                    <input type="text" className="form-control" id="project-name" name="project_name" onChange={this.onProjectNameChange.bind(this)} />
                  </div>
                  <div className={`form-group ${styles.formGroup}`}>
                    <label htmlFor="description" className="col-form-label">Description</label>
                    <textarea className="form-control" id="description" rows="4" name="description" onChange={this.onDescriptionChange.bind(this)}></textarea>
                  </div>
                </form>
              </div>
              <div className={`modal-footer ${styles.modalFooter} ${styles.editModalFooter}`}>
                <button type="button" className={`btn btn-default ${styles.cancelBtn}`} data-dismiss="modal">Cancel</button>
                <button type="button" className={`btn btn-primary text-white ${styles.saveBtn}`} onClick={(e) => this.handleSubmit(project)}>Save Changes</button>
              </div>
            </div>
          </div>
        </div>
      </div>
    )
  }
}

export default EditProjectModal;

【问题讨论】:

    标签: javascript reactjs ecmascript-6 bootstrap-modal


    【解决方案1】:

    首先,您需要在填充项目表时将当前行项目详细信息作为道具传递给 EditProjectModal(我将其命名为 theProject):

       <tbody className="scrollContent">
        {
            projects.map((project, i) => {
                return (
                        <tr key={i}>
                            <td>{project.project_name}</td>
                            <td>{project.description}</td>
                            <td>
                                <EditProjectModal projects={projects} theProject={project} />
                            </td>
                        </tr>
                    );
            })
        }
       </tbody>
    

    然后在EditProjectModal中,可以设置成这样的状态:

    constructor(props) {
        super(props);
        this.state = {
          project_name: this.props.theProject.project_name,
          description: this.props.theProject.description
        }
      }
    }
    

    然后你需要在 EditProjectModal 中设置输入的值,状态如下:

    <form>
        <div className={`form-group ${styles.formGroup} ${styles.projName}`}>
            <label htmlFor="project-name" className="col-form-label">Project Name</label>
            <input type="text" className="form-control" id="project-name" 
                   name="project_name" 
                   value={this.state.project_name}
                   onChange={this.onProjectNameChange.bind(this)} />
        </div>
        <div className={`form-group ${styles.formGroup}`}>
            <label htmlFor="description" className="col-form-label">Description</label>
            <textarea className="form-control" id="description" 
                      rows="4" name="description" 
                      value={this.state.description}
                      onChange={this.onDescriptionChange.bind(this)}></textarea>
        </div>
    </form>
    

    【讨论】:

    • 我尝试了您的建议 Ashkan,现在当我单击行打开模式时,我可以在输入字段上显示行数据。但是,无论我单击哪个数据行打开模式,我都只能获取第一行的数据。关于如何获取所选行的数据的任何想法?
    • 嘿,你介意看看我的问题吗?谢谢stackoverflow.com/questions/66011985/…
    • 问题是每次点击行都不会重新初始化初始状态。您需要使用 setState() 设置显式值,或者尝试为每一行添加不同的键,这会导致每次打开一行时重新渲染。
    【解决方案2】:

    可以通过将行详细信息作为道具传递给EditProjectModal来初始化编辑表单,并且可以将道具分配为EditProjectModal的状态以简化处理。然后您可以为input和@987654324赋值@使用value属性。value属性可以被赋予对应的状态。

    class EditProjectModal extends Component {  
      constructor(props) {
        super(props);
        this.state = {
          project_name: '',
          description: ''
        }
      }
      ComponentWillMount() {
           this.setState(project_name: this.props.project.project_name,description:this.props.project.description)
     }
    render() {
     ....//rest of the code
              <form>
                  <div className={`form-group ${styles.formGroup} ${styles.projName}`}>
                    <label htmlFor="project-name" className="col-form-label">Project Name</label>
                    <input type="text" className="form-control" id="project-name" name="project_name" onChange={this.onProjectNameChange.bind(this)}  value={this.state.project_name}/>
                  </div>
                  <div className={`form-group ${styles.formGroup}`}>
                    <label htmlFor="description" className="col-form-label">Description</label>
                    <textarea className="form-control" id="description" rows="4" name="description" onChange={this.onDescriptionChange.bind(this)} value={this.state. description}/>
                  </div>
                </form>
    }
    

    您需要将项目传递为

     <tbody className="scrollContent">
       {
       projects.map((project, i) => {
       return (
       <tr key={i}>
          <td>{project.project_name}</td>
          <td>{project.description}</td>
          <td>
             <EditProjectModal project={project} />
          </td>
       </tr>
       );
       })
       }
    </tbody>
    

    【讨论】:

    • 我尝试了您的建议 Harikrishnan,现在当我单击行打开模式时,我可以在输入字段中显示行数据。但是,无论我单击哪个数据行打开模式,我都只能获取第一行的数据。关于如何获取所选行的数据的任何想法?
    • @SamWhite 我已更新代码请检查,而不是将整个项目作为道具传递,只需传递您从 map 方法获得的每个项目
    • 感谢您再次回复我。我只是尝试过,它仍然没有工作。无论我点击哪个表格行,我仍然只看到表格第一行的数据被拉取。
    • @SamWhite 如果可能的话,你能把你的代码放在codesandbox或jsfiddle中,以便我们检查工作
    • 我刚刚在这里用相关代码创建了沙箱。这是链接codesandbox.io/s/zwo7nwx2kx。我无法将此作为一个工作示例。如果您仍然可以弄清楚问题所在,那就太好了。否则,我会继续努力。
    猜你喜欢
    • 1970-01-01
    • 2021-03-24
    • 1970-01-01
    • 1970-01-01
    • 2022-06-22
    • 2020-09-02
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多