繁体   English   中英

如何在React-Redux中更改状态时关闭模态对话框?

[英]How to close the Modal Dialog when state changed in React-Redux?

基本上,我想在Redux-Store中更改Global状态时更改Component中的UI状态。

我的方案如下:

  1. 当用户单击“添加学生”按钮时显示模态表单
  2. 用户单击“保存”按钮时显示“正在保存...”
  3. 如果发生错误,对话框应保持打开状态并显示错误
  4. 如果插入正常,则应自动关闭对话框

在此输入图像描述

我已经达到了前3分,但我在第4点陷入困境,并且在成功插入后不知道如何实现Close功能。

我想在Redux-Store中更改isSubmitting / error时运行以下示例代码。 但是,我不知道在哪里运行它。 我试图将它放在render()方法中,但它不起作用,我无法打开对话框。

检查和关闭模态的代码

if (isSubmitting === false && error === null)
     this.setState({ add: false });

我不想将UI状态(例如IsModalOpen - bool)提升到Global Redux商店。 我已经将UI状态'isSubmitting'放入Redux中,我不想继续将UI状态添加到Redux Store中。

您能否建议我在成功插入后如何关闭对话框?

我把示例代码放在CodeSandbox上,就在这里

减速器

const initialState = {
      isSubmitting: false,
      error: null,
      student: null
    };

function rootReducer(state = initialState, action) {
  switch (action.type) {
    case "STUDENT_ADD_BEGIN": {
      return {
        ...state,
        isSubmitting: true
      };
    }
    case "STUDENT_ADD_SUCCESS": {
      return {
        ...state,
        student: action.payload,
        error: null,
        isSubmitting: false
      };
    }
    case "STUDENT_ADD_ERROR": {
      return {
        ...state,
        isSubmitting: false,
        error: action.error,
        student: null
      };
    }
    default:
      return state;
  }
}

export default rootReducer;

集装箱/页

class addStudentPage extends Component {
  constructor(props) {
    super(props);
    this.state = {
      dataList: [],
      add: false,
      edit: false,
      dataItem: {}
    };
  }

  getInitialState() {
    return {
      id: "",
      name: "TTCG"
    };
  }

  componentDidMount() {
    this.setState({
      dataItem: this.getInitialState()
    });
  }

  toggleAdd = () => {
    this.setState(prevState => ({
      add: !prevState.add
    }));
  };

  showAddNew = () => {
    this.toggleAdd();

    this.setState({
      dataItem: this.getInitialState()
    });
  };

  updateItemState = event => {
    const field = event.target.name;
    const value = event.target.value;
    let item = this.state.dataItem;

    item[field] = value;

    return this.setState({ dataItem: item });
  };

  handleAddNew = () => {
    let item = this.state.dataItem;
    item["id"] = uuid.v4();
    console.info(item);
    this.props.addStudentAction(item);
  };

  render() {
    const { isSubmitting, error } = this.props;

    return (
      <Container>
        <h1>Students</h1>
        <Button onClick={this.showAddNew} color="link">
          Add New Student
        </Button>
        {this.state.add && (
          <AddStudent
            toggle={this.toggleAdd}
            modal={this.state.add}
            item={this.state.dataItem}
            onChange={this.updateItemState}
            onAddNew={this.handleAddNew}
            isSubmitting={isSubmitting}
            error={error}
          />
        )}
        {this.props.student && (
          <h6>You have added a new student named: {this.props.student.name}</h6>
        )}
      </Container>
    );
  }
}

const mapStateToProps = state => {
  return {
    isSubmitting: state.studentReducer.isSubmitting,
    error: state.studentReducer.error,
    student: state.studentReducer.student
  };
};

const mapDispatchToProps = {
  addStudentAction: item => addStudentAction(item)
};

模态表格

export default class StudentAdd extends Component {
  render() {
    const {
      modal,
      toggle,
      item,
      onChange,
      onAddNew,
      isSubmitting,
      error
    } = this.props;

    return (
      <Modal isOpen={modal} toggle={toggle} centered>
        <ModalHeader toggle={toggle}>Add New Student</ModalHeader>
        <ModalBody>
          {error && <Alert color="danger">{error}</Alert>}
          <Form>
            <FormGroup>
              <Label for="Name">Name</Label>
              <Input
                type="text"
                name="name"
                id="Name"
                value={item.name}
                onChange={onChange}
              />{" "}
              type 'error' to simulate error
            </FormGroup>
          </Form>
        </ModalBody>
        <ModalFooter>
          <Button color="primary" onClick={onAddNew} disabled={isSubmitting}>
            {isSubmitting ? "Saving..." : "Save"}
          </Button>{" "}
          <Button color="secondary" onClick={toggle}>
            Cancel
          </Button>
        </ModalFooter>
      </Modal>
    );
  }
}

更新

它可以通过使用componentDidUpdate生命周期方法来实现,如下所示:在导出状态之前,请注意检查道具和状态。

componentDidUpdate(prevProps) {
    const { isSubmitting, error } = this.props;
    if (isSubmitting !== prevProps.isSubmitting || error !== prevProps.error) {
      if (isSubmitting === false && error === null)
        this.setState({ add: false });
    }
  }

或者您可以使用getDerivedStateFromProps生命周期方法重新计算道具。 但我发现很难使用componentDidUpdate

实现这一点有点复杂和笨拙,但你仍然可以强制执行以下行为:

在行动中使用Promise

export const addStudentAction = item => {
    return function(dispatch) {
        dispatch({ type: 'STUDENT_ADD_BEGIN' });

        setTimeout(() => {
            if (item.name !== 'error') {
                // HERE
                Promise.resolve(
                    dispatch({ type: 'STUDENT_ADD_SUCCESS', payload: item })
                );
                dispatch(closeModal('AddStudentModal'));
            } else {
                // HERE
                Promise.resolve(
                    dispatch({
                        type: 'STUDENT_ADD_ERROR',
                        error: 'Intentional Error Message'
                    })
                );
            }
        }, 1000);
    };
};

在保存项目后,可以让你链接你的setState并关闭模态:

handleAddNew = () => {
    let item = this.state.dataItem;
    item['id'] = uuid.v4();
    this.props.dispatch(addStudentAction(item)).then(() => {
        console.log('boom');
        this.setState({ add: false });
    });
};

需要注意的是,为了做到这一点,你就需要使用dispatch明确你的行动的每一个动作,而不是使用mapDispatchToProps

我修改了代码框,以便您可以检查所需的行为。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM