【问题标题】:Use react modal bootstrap to edit items in a map list使用 react modal bootstrap 编辑地图列表中的项目
【发布时间】:2021-09-22 22:03:51
【问题描述】:

我的应用程序有两个组件,一个呈现列表,另一个呈现表单:

我想使用相同的组件来创建新类别并编辑已经存在的类别。

创建类别已经运行良好,但要进行编辑,需要将列表中类别的 id 传递给模态框内的表单,因为我是 react 新手,我需要一些帮助。提前致谢。

调用列表文件,

Categories.jsx

import React, { Component } from 'react'
import { Alert, Modal, Button } from "react-bootstrap";
import Datatable from '../../../globalcomponents/datatable/Datatable';
import CategoryForm from './CategoryForm';

const Api = require('../../api/CategoriesApi.js')

class Categories extends Component {
  constructor(props) {
    super(props) 
    this.state = {
      categories: [],
      isLoaded: false,
      error: null,
      isOpen: false
    }
  }

  openModal = () => this.setState({ isOpen: true });
  closeModal = () => this.setState({ isOpen: false });

  componentDidMount() {
    Api.getCategories()
      .then(response => {
        const [error, data] = response
        if (error) {
          this.setState({
            isLoaded: true,
            categories: [],
            error: data
          })
        } else {
          this.setState({
            isLoaded: true,
            categories: data
          })
        }
      })
  } 

  render() {
    const { error, isLoaded, categories } = this.state

    if (error) {

      return (
        <Alert color="danger">
          Error: {error}
        </Alert>
      )

    } else if (!isLoaded) {

      return (
        <Alert color="primary">
          Loading...
        </Alert>
      )

    } else {

      return (
        <>            
            <Button className="float-right" variant="primary" onClick={this.openModal}>
              Adicionar
            </Button>
            
            <h4 className="mt-4 mb-4">Categorias de investimentos</h4>
            <Datatable>
              <table className="table table-striped my-4 w-100">
              <thead>
                <tr>
                  <th>ID</th>
                  <th>Title</th>
                  <th>Url (Slug)</th>
                  <th></th>
                </tr>
              </thead>
              <tbody>
                {categories.map(category => (
                  <tr key={category.id}>
                    <td>{category.id}</td>
                    <td>{category.title}</td>
                    <td>{category.slug}</td>
                    <td>
                    

                      <Button className="float-right mr-2" variant="primary" onClick={this.openModal}>
                        Modal Edit
                      </Button>

                    </td>
                  </tr>
                ))}
              </tbody>
            </table>
            </Datatable>        
            
            <Modal show={this.state.isOpen} onHide={this.closeModal}>
              <Modal.Header closeButton>
                <Modal.Title>Adicionar / Editar</Modal.Title>
              </Modal.Header>
              <Modal.Body>
                <CategoryForm />
              </Modal.Body>
              <Modal.Footer>
                <Button variant="secondary" onClick={this.closeModal}>
                  Close
                </Button>
              </Modal.Footer>
            </Modal>
            </>



     )

    }

  }
}

export default Categories


表单文件用于创建或编辑类别。它被称为: CategoryForm.jsx

import React, { Component } from 'react'
import { Redirect } from 'react-router'
import { Row, Col, Alert, Button, Form, FormGroup, Label, Input } from 'reactstrap'

const Api = require('../../api/CategoriesApi.js')

class CategoryForm extends Component {
  constructor(props) {
    super(props)

    this.state = {
      category: {
        id: this.getCategoryId(props),
        title: '',
        slug: '',
      },
      redirect: null,
      errors: []
    }

    this.setTitle = this.setTitle.bind(this)
    this.setSlug = this.setSlug.bind(this)
    
    this.handleSubmit = this.handleSubmit.bind(this)
  }

  getCategoryId(props) {
    try {
      return props.match.params.id
    } catch (error) {
      return null
    }
  }

  setTitle(event) {
    let newVal = event.target.value || ''
    this.setFieldState('title', newVal)
  }

  setSlug(event) {
    let newVal = event.target.value || ''
    this.setFieldState('slug', newVal)
  }

  setFieldState(field, newVal) {
    this.setState((prevState) => {
      let newState = prevState
      newState.category[field] = newVal
      return newState
    })
  }

  handleSubmit(event) {
    event.preventDefault()

    let category = {
      title: this.state.category.title,
      slug: this.state.category.slug,
    }

    Api.saveCategory(category, this.state.category.id)
      .then(response => {
        const [error, errors] = response
        if (error) {
          this.setState({
            errors: errors
          })
        } else {
          this.setState({
            // reload categories
            redirect: '/admin'
          })
        }
      })
  }

  componentDidMount() {
    if (this.state.category.id) {
      Api.getCategory(this.state.category.id)
        .then(response => {
          const [error, data] = response
          if (error) {
            this.setState({
              errors: data
            })
          } else {
            this.setState({
              category: data,
              errors: []
            })
          }
        })
    }
  }

  render() {
    const { redirect, category, errors } = this.state

    if (redirect) {
      return (
        <Redirect to={redirect} />
      )
    } else {

      return (
        <>
          <Row>
            <Col>
              {errors.length > 0 &&
                <div>
                  {errors.map((error, index) =>
                    <Alert color="danger" key={index}>
                      {error}
                    </Alert>
                  )}
                </div>
              }

              <Form onSubmit={this.handleSubmit}>
                <FormGroup>
                  <Label for="title">Title</Label>
                  <Input type="text" name="title" id="title" value={category.title} placeholder="Enter title" onChange={this.setTitle} />
                </FormGroup>
                <FormGroup>
                  <Label for="slug">Slug</Label>
                  <Input type="text" name="slug" id="slug" value={category.slug} placeholder="Enter slug" onChange={this.setSlug} />
                </FormGroup>
                <Button color="success">Submit</Button>
              </Form>
            </Col>
          </Row>
        </>
      )
    }
  }
}

export default CategoryForm



【问题讨论】:

    标签: reactjs


    【解决方案1】:

    您没有在 Categories.jsx 中传递 id。您可以将 id 设置为历史状态,也可以通过组件传递它 道具钻。

    设置历史状态Programmatically set params in React Router v4

    或者您可以将 id 传递给组件并在组件中处理 DidMount 事件。

    here is the code sandbox link

    Categories.jsx


    /** Create a id variable in state. **/
    class Categories extends Component {
                            constructor(props) {
                                super(props);
                                this.state = {
                                    categories: [],
                                    isLoaded: false,
                                    error: null,
                                    isOpen: false,
                                   --> id: null <--
                                };
                            }
                
    /** change the openModal code to something like this. **/
    openModal = (id) => {
                      this.setState( (prev) => {
                          const state = prev.state;
                          return { ...state, id: id, isOpen:true };
                        });
                        };
        
                               
    /** while Onclick set the id in the state. **/
    <Datatable>
                        <table className="table table-striped my-4 w-100">
                          <thead>
                            <tr>
                              <th>ID</th>
                              <th>Title</th>
                              <th>Url (Slug)</th>
                              <th></th>
                            </tr>
                          </thead>
                          <tbody>
                            {categories.map((category) => (
                              <tr key={category.id}>
                                <td>{category.id}</td>
                                <td>{category.title}</td>
                                <td>{category.slug}</td>
                                <td>
                                  <Button
                                    className="float-right mr-2"
                                    variant="primary"
                                 -->   onClick={() =>this.openModal(category.id)}
                                  >
                                    Modal Edit
                                  </Button>
                                </td>
                              </tr>
                            ))}
                          </tbody>
                        </table>
                      </Datatable>
                   
                 
    /** Pass the id prop for CategoryForm Component in Modal body from the state. **/
    
     <Modal show={this.state.isOpen} onHide={this.closeModal} >
                                  <Modal.Header closeButton>
                                    <Modal.Title>Adicionar / Editar</Modal.Title>
                                  </Modal.Header>
                                  <Modal.Body>
                                  -->  <CategoryForm id={this.state.id || null} />
                                  </Modal.Body>
                                  <Modal.Footer>
                                    <Button variant="secondary" onClick=  {this.closeModal}>
                                      Close
                                    </Button>
                                  </Modal.Footer>
                                </Moddal>
    

    CategoryForm.jsx

    在componentDidMount有条件地检查props中是否有id变量。


      componentDidMount() {
        **// Check if props.id is available** 
            if (** this.state.category.id || this.props.id **) {
                  **const id = this.state.category.id || this.props.id;**
                    Api.getCategory(id).then((response) => {
                        const [error, data] = response;
                        if (error) {
                            this.setState({
                                errors: data
                            });
                        } else {
                            alert(id);
        
                            this.setState({
                                category: data,
                                errors: []
                            });
                        }
                    });
            }
        }
    

    【讨论】:

      【解决方案2】:

      您可以向Categories 添加更多状态以跟踪有关模式的其他数据。

      *我这里只包含了代码中的高亮部分;为简洁起见,省略了很多。

      Categories.jsx:

        constructor(props) {
          super(props) 
          this.state = {
            categories: [],
            isLoaded: false,
            error: null,
            isOpen: false,
            modalData: null,
          }
        }
      
        openModal = (modalData) => this.setState({ isOpen: true, modalData });
        closeModal = () => this.setState({ isOpen: false, modalData: null });
      
        //'create' dialog button
              <Button className="float-right" variant="primary" onClick={e => this.openModal({modalType: 'create'})}>
                Adicionar
              </Button>
      
      
          //here are the table rows:
         {categories.map(category => (
                    <tr key={category.id}>
                      <td>{category.id}</td>
                      <td>{category.title}</td>
                      <td>{category.slug}</td>
                      <td>
                      
      
                        <Button className="float-right mr-2" variant="primary" onClick={e => this.openModal({modalType: 'edit', categoryId: category.id})}>
                          Modal Edit
                        </Button>
      
                      </td>
                    </tr>
                  ))}
      
            //the modal. pass modalData as a prop:
           <Modal show={this.state.isOpen} onHide={this.closeModal}>
                <Modal.Header closeButton>
                  <Modal.Title>Adicionar / Editar</Modal.Title>
                </Modal.Header>
                <Modal.Body>
                  <CategoryForm modalData={modalData} />
                </Modal.Body>
                <Modal.Footer>
                  <Button variant="secondary" onClick={this.closeModal}>
                    Close
                  </Button>
                </Modal.Footer>
              </Modal>
      

      CategoryForm.jsx:

        //get id from props:
        getCategoryId(props) {
          return (props.modalData.modalType === 'edit') ? props.modalData.categoryId : false;
      
          //I don't know if this needs to be here:
          //try {
          //  return props.match.params.id
          //} catch (error) {
          //  return null
          //}
        }
      

      您可能需要重构 CategoryForm.jsx。例如,categoryId 现在是一个 prop,因此它不需要在 state 中重复。

      【讨论】:

        猜你喜欢
        • 2013-03-21
        • 1970-01-01
        • 2018-07-06
        • 2014-06-15
        • 2022-11-30
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多