Javascript 当React Redux中的状态更改时,如何关闭模式对话框?

Javascript 当React Redux中的状态更改时,如何关闭模式对话框?,javascript,reactjs,redux,react-redux,Javascript,Reactjs,Redux,React Redux,基本上,当Redux存储中的全局状态发生更改时,我希望更改组件中的UI状态 我的设想如下: 当用户单击“添加学生”按钮时显示模式窗体 当用户单击“保存”按钮时显示“保存…” 如果发生错误,对话框应保持打开状态并显示错误 如果插入正常,对话框应自动关闭 我已经获得了前3分,但我仍停留在第4点,不知道如何在成功插入后实现Close功能 每当在Redux存储中更改IssubMatting/error时,我都希望运行以下示例代码。但是,我不知道在哪里运行它。我试图将它放在render()方法中,但它不

基本上,当Redux存储中的全局状态发生更改时,我希望更改组件中的UI状态

我的设想如下:

  • 当用户单击“添加学生”按钮时显示模式窗体
  • 当用户单击“保存”按钮时显示“保存…”
  • 如果发生错误,对话框应保持打开状态并显示错误
  • 如果插入正常,对话框应自动关闭
  • 我已经获得了前3分,但我仍停留在第4点,不知道如何在成功插入后实现
    Close
    功能

    每当在Redux存储中更改IssubMatting/error时,我都希望运行以下示例代码。但是,我不知道在哪里运行它。我试图将它放在render()方法中,但它不起作用,我无法再打开对话框

    代码以检查并关闭模式

    我不想将UI状态(例如IsModalOpen-bool)提升到全局Redux商店中。我已经将UI状态“isSubmitting”放入Redux,我不想继续将UI状态添加到Redux存储中

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

    我把示例代码放在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)
    };
    

    或者您可以使用
    getDerivedStateFromProps
    lifecycle方法重新计算props。但是我发现它比
    组件diddupdate
    更难使用

    实现这一点有点复杂和笨拙,但您仍然可以按如下方式强制执行该行为:

    在行动中使用
    承诺

    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);
        };
    };
    
    将允许您在保存项目后立即链接
    设置状态
    ,并关闭模式:

    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


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

    谢谢您的建议。但是,它不起作用。今天早上,我将ui状态提升到Redux上,并意外地重写了CodeSandbox。这就是为什么当你尝试的时候它会起作用。我分叉并回滚了我最近的更改,并按照您的建议在这个新的代码沙盒中应用。您可以注意到,它甚至不会触发调度。好的,然后修改您的减速机。如果要从减速器控制模态,应在modalReducer中将isAddStudentModalOpen从true切换为false,就像之前在状态中使用this.props.add所做的那样。例子:
    componentDidUpdate(prevProps) {
        const { isSubmitting, error } = this.props;
        if (isSubmitting !== prevProps.isSubmitting || error !== prevProps.error) {
          if (isSubmitting === false && error === null)
            this.setState({ add: false });
        }
      }
    
    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);
        };
    };
    
    handleAddNew = () => {
        let item = this.state.dataItem;
        item['id'] = uuid.v4();
        this.props.dispatch(addStudentAction(item)).then(() => {
            console.log('boom');
            this.setState({ add: false });
        });
    };