【问题标题】:How do I reset modal props on close如何在关闭时重置模态道具
【发布时间】:2019-08-06 16:32:31
【问题描述】:

我有一个组件,DeleteRoute,它只是一个 Modal 的包装器。它允许我删除一个“Route”实体。

我使用 React 和 Redux 来维护数据和状态。

我正在努力使用正确的架构来使模式正常工作。我不喜欢将所有状态都放在父容器中,因为它使父容器变得混乱。所以我把 redux 动作放在了 modal 里面。这样我从父级传入一个路由,但是从 DeleteRoute 组件内的 redux 存储中调用“deleteRoute”,我可以显示成功和错误消息。

这一切都很好,除了我关闭并重新打开模式,之​​前的成功/错误消息仍然显示。这是因为关闭/打开是通过父级的切换完成的,但父级无法重置子道具。

我以为我可以只传递父级中的成功和错误属性,并且无论何时父级重新渲染它都会重置它们,但事实并非如此(尽管它在 isOpen 更改时重新渲染)。

class DeleteRoute extends React.Component {
  constructor(props) {
    super(props);

    this.deleteRoute = this.deleteRoute.bind(this);
  }

  deleteRoute() {
    this.props.deleteRoute(this.props.route);
  }

  render() {
    var route = this.props.route || {};

    return (
      <div>
        <Modal
          isOpen={this.props.isOpen}
          toggle={this.props.toggle}
        >
          <ModalHeader toggle={this.props.toggle}>Delete Route</ModalHeader>

          <ModalBody>
            {this.props.isLoading && <Spinner color="primary" />}

            <Alert color="danger" isOpen={this.props.error}>{this.props.error}</Alert>
            <Alert color="success" isOpen={this.props.success}>Deleted successfully</Alert>

            <Form>
              <Row form>
                <Col>
                  <FormGroup>
                    <Label for="CssPlatform">Css Platform</Label>
                    <Input disabled name="CssPlatform" type="text" value={route.CSSPlatform} />
                  </FormGroup>
                </Col>

                <Col>
                  <FormGroup>
                    <Label for="ProdManager">Prod Manager</Label>
                    <Input disabled name="ProdManager" type="text" value={route.ProdManager} />
                  </FormGroup>
                </Col>
              </Row>

              <Row form>
                <Col>
                  <FormGroup>
                    <Label for="CssProduct">Css Product</Label>
                    <Input disabled name="CssProduct" type="text" value={route.CSSProduct} />
                  </FormGroup>
                </Col>

                <Col>
                  <FormGroup>
                    <Label for="ProgSupervisor">Prog Supervisor</Label>
                    <Input disabled name="ProgSupervisor" type="text" value={route.ProgSupervisor} />
                  </FormGroup>
                </Col>
              </Row>

              <Row form>
                <Col>
                  <FormGroup>
                    <Label for="CssSubProduct">Css SubProduct</Label>
                    <Input disabled name="CssSubProduct" type="text" value={route.CSSSubProduct} />
                  </FormGroup>
                </Col>

                <Col>
                  <FormGroup>
                    <Label for="RallyProject">Rally Project</Label>
                    <Input disabled name="RallyProject" type="text" value={route.RallyProject} />
                  </FormGroup>
                </Col>
              </Row>

              <Row form>
                <Col>
                  <FormGroup check inline>
                    <Label check>
                      <Input disabled name="CssProductActive" type="checkbox" checked={route.CSSProductActive} />
                      Css Product Active
                    </Label>
                  </FormGroup>
                </Col>

                <Col>
                  <FormGroup check inline>
                    <Label check>
                      <Input disabled name="CssSubProductActive" type="checkbox" checked={route.CSSSubProductActive} />
                      Css SubProduct Active
                    </Label>
                  </FormGroup>
                </Col>
              </Row>
            </Form>
          </ModalBody>

          <ModalFooter>
            <Button color="primary" onClick={this.deleteRoute}>Delete Route</Button>{' '}
            <Button color="secondary" onClick={this.props.toggle}>Cancel</Button>
          </ModalFooter>
        </Modal>
      </div>
    );
  }
}

export default connect(
  state => state.deleteRouteReducer,
  dispatch => bindActionCreators(actionCreators, dispatch))(DeleteRoute);


render() {
    return (
      <div>
        <h2>Routes</h2>
        <p>Routes define how items from CSS get imported into Rally. Use routes to connect a Rally project to a set of criteria in CSS.</p>
        <div>
          <AddRoute isOpen={this.props.showAddRoute} toggle={this.toggleAddRoute} />
          <DeleteRoute error={this.props.deleteRouteError} success={this.props.deleteRouteSuccess} isOpen={this.props.showDeleteRoute} route={this.props.selectedRoute} toggle={this.toggleDeleteRoute} />

          <DataTable
            actions={[
              { Click: this.toggleAddRoute, Color: 'green', Icon: 'MdAdd', ToolTip: "Add new route" },
              { Click: this.toggleEditRoute, Color: 'orange', Icon: 'MdEdit', ToolTip: "Edit route", RowAction: true },
              { Click: this.toggleDeleteRoute, Color: 'red', Icon: 'MdRemove', ToolTip: "Delete route", RowAction: true },
            ]}
            columns={[
              { Title: "Platform", Field: "CSSPlatform" },
              { Title: "Product", Field: "CSSProduct" },
              { Title: "SubProduct", Field: "CSSSubProduct" },
              { Title: "ProdManager", Field: "ProdManager" },
              { Title: "ProgSupervisor", Field: "ProgSupervisor" },
              { Title: "Product Active?", Field: "CSSProductActive" },
              { Title: "SubProduct Active?", Field: "CSSSubProductActive" },
              { Title: "Rally Project", Field: "RallyProject" },
              { Title: "Rally Url", Field: "RallyUrl" }
            ]}
            data={this.props.routes}
            edit={this.editRoute}
            isLoading={this.props.isLoading} />
        </div>
      </div>
    );

【问题讨论】:

  • 您应该扩展您的 deleteRoute 操作以同时从状态中删除错误。
  • 我把错误和成功放在了 props 中,以便 Redux 可以设置它。所以 deleteRoute 中的“setState”不起作用。也许我不应该从 Redux 控制那些?
  • 这些错误/成功消息在哪里存在。
  • 它们存在于 DeleteRoute 的 props 中,在 ajax 调用 api 后由 Redux 设置。

标签: reactjs redux modal-dialog


【解决方案1】:

我最终添加了一个 redux 操作来重置成功和错误道具,然后在模式关闭时调用它。我认为这符合正确的 redux 架构,但如果有人有更好的解决方案,我愿意接受。


class DeleteRoute extends React.Component {
  constructor(props) {
    super(props);

    this.deleteRoute = this.deleteRoute.bind(this);
    this.toggle = this.toggle.bind(this);
  }

  deleteRoute() {
    this.props.deleteRoute(this.props.route);
  }

  toggle() {
    if (this.props.isOpen) {
      // reset the error and success messages on close
      this.props.initialize();
    }

    this.props.toggle();
  }

  render() {
    var route = this.props.route || {};

    return (
      <div>
        <Modal
          isOpen={this.props.isOpen}
          toggle={this.toggle}
        >
          <ModalHeader toggle={this.toggle}>Delete Route</ModalHeader>

          <ModalBody>
            {this.props.isLoading && <Spinner color="primary" />}

            <Alert color="danger" isOpen={this.props.error}>{this.props.error}</Alert>
            <Alert color="success" isOpen={this.props.success}>Deleted successfully</Alert>

            <Form>
              <Row form>
                <Col>
                  <FormGroup>
                    <Label for="CssPlatform">Css Platform</Label>
                    <Input disabled name="CssPlatform" type="text" value={route.CSSPlatform} />
                  </FormGroup>
                </Col>

                <Col>
                  <FormGroup>
                    <Label for="ProdManager">Prod Manager</Label>
                    <Input disabled name="ProdManager" type="text" value={route.ProdManager} />
                  </FormGroup>
                </Col>
              </Row>

              <Row form>
                <Col>
                  <FormGroup>
                    <Label for="CssProduct">Css Product</Label>
                    <Input disabled name="CssProduct" type="text" value={route.CSSProduct} />
                  </FormGroup>
                </Col>

                <Col>
                  <FormGroup>
                    <Label for="ProgSupervisor">Prog Supervisor</Label>
                    <Input disabled name="ProgSupervisor" type="text" value={route.ProgSupervisor} />
                  </FormGroup>
                </Col>
              </Row>

              <Row form>
                <Col>
                  <FormGroup>
                    <Label for="CssSubProduct">Css SubProduct</Label>
                    <Input disabled name="CssSubProduct" type="text" value={route.CSSSubProduct} />
                  </FormGroup>
                </Col>

                <Col>
                  <FormGroup>
                    <Label for="RallyProject">Rally Project</Label>
                    <Input disabled name="RallyProject" type="text" value={route.RallyProject} />
                  </FormGroup>
                </Col>
              </Row>

              <Row form>
                <Col>
                  <FormGroup check inline>
                    <Label check>
                      <Input disabled name="CssProductActive" type="checkbox" checked={route.CSSProductActive} />
                      Css Product Active
                    </Label>
                  </FormGroup>
                </Col>

                <Col>
                  <FormGroup check inline>
                    <Label check>
                      <Input disabled name="CssSubProductActive" type="checkbox" checked={route.CSSSubProductActive} />
                      Css SubProduct Active
                    </Label>
                  </FormGroup>
                </Col>
              </Row>
            </Form>
          </ModalBody>

          <ModalFooter>
            <Button color="primary" onClick={this.deleteRoute}>Delete Route</Button>{' '}
            <Button color="secondary" onClick={this.toggle}>Cancel</Button>
          </ModalFooter>
        </Modal>
      </div>
    );
  }
}

export default connect(
  state => state.deleteRouteReducer,
  dispatch => bindActionCreators(actionCreators, dispatch))(DeleteRoute);

和 redux 位

import axios from 'axios';

// actions
const deleteRouteType        = "DELETE_ROUTE";
const deleteRouteFailureType = "DELETE_ROUTE_FAILURE";
const deleteRouteSuccessType = "DELETE_ROUTE_SUCCESS";
const initializeType         = "DELETE_ROUTE_INITIALIZE";

const initialState = { error: null, success: null };

// action creators
export const actionCreators = {
  initialize: () => (dispatch) => {
    dispatch({ type: initializeType });
  },

  deleteRoute: (route) => async (dispatch) => {
    dispatch({ type: deleteRouteType });

    axios
      .delete(`api/route`, route)
      .then(res => {
        if (res.data.error) {
          dispatch({ type: deleteRouteFailureType, payload: res.data.errorMessage });
        }
        else {
          dispatch({ type: deleteRouteSuccessType, payload: res.data.data });
        }
      })
      .catch(err => {
        dispatch({ type: deleteRouteFailureType, payload: err.message });
      });
  }
};

// reducers
export const reducer = (state, action) => {
  state = state || initialState;

  switch (action.type) {
    case initializeType:
      return {
        ...state,
        error: null,
        isLoading: false,
        success: false
      };

    case deleteRouteType:
      return {
        ...state,
        error: null,
        isLoading: true,
        success: false
      };

    case deleteRouteFailureType:
      return {
        ...state,
        error: action.payload,
        isLoading: false,
        success: false
      };

    case deleteRouteSuccessType:
      return {
        ...state,
        error: null,
        isLoading: false,
        success: true
      };

    default:
      return state;
  }
};

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2016-12-03
    • 2019-09-19
    • 1970-01-01
    • 1970-01-01
    • 2014-03-11
    • 2020-06-20
    • 1970-01-01
    • 2020-06-09
    相关资源
    最近更新 更多