首页 > 解决方案 > 使用模式框在 React 中编辑项目后重新加载列表 - 将功能从一个组件传递到另一个组件

问题描述

我在一个 CRUD 表中工作,为此我创建了 2 个文件,一个列出该表,另一个用于编辑列表中的每个项目。我正在使用模态进行编辑或创建。

与 api 和数据库的交互工作正常。但是有两个问题正在发生。

  1. 点击CategoryForm文件中的Button Submit后,modal没有关闭,还是打开了,不知道怎么把这个函数从list传给form。并从那里使用它。

  2. 该表不会重新加载插入数据的新行。(数据正确地进入 api 和数据库)。还认为需要将它从列表组件传递到表单并从那里调用它。

提前致谢。我不知道拥有两个包含两个组件的文件是否是最好的解决方案,所以我愿意接受建议。

这是名为Categories.jsx的列表文件


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

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

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

  openModal = (id) => {
    this.setState( (prev) => {
        const state = prev.state;
        return { ...state, id: id, 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
          })
        }
      })
  } 

  removeCategory = (id) => {
    var categories = [...this.state.categories];
    var index  = categories.findIndex(function(item, i){return item.id === id})
    categories.splice(index, 1);
    this.setState({categories});
    Api.deleteCategory(id)
}
  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={e => 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="btn btn-danger float-right" 
                      onClick={(event) =>
                         this.removeCategory(category.id)
                      }
                      ><FaTrashAlt /></Button>
                      <Button
                        className="btn btn-success float-right mr-2 "
                        onClick={() =>this.openModal(category.id)}
                      >
                        <FaPencilAlt />
                      </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 id={this.state.id || null}/>
              </Modal.Body>
              <Modal.Footer>
                <Button variant="secondary" onClick={this.closeModal}>
                  Close
                </Button>
              </Modal.Footer>
            </Modal>
            </>



     )

    }

  }
}

export default Categories

这是表单文件:


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: [],
      reload: false
    }

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


  getCategoryId(props) {
    try {
      return props.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(
            () => this.setState({reload: true})
          )
        
      
        }
      })
  }

  componentDidMount() {
      if (this.props.id ) {
        Api.getCategory(this.props.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

解决方案


在一个地方你在另一个地方const [error, data] = responseconst [error, errors] = response这是故意的吗?

您没有为关闭模式传递任何 cb 或将数据更新到<CategoryForm id={this.state.id || null}/>.

Categories.jsx组件不知道您何时更新 API 上的数据。

也许像

<CategoryForm id={this.state.id || null} 
    onSubmit={() => {
    closeModal()
    Api.getCategories()
          .then(...
    
    }}/>`

推荐阅读