源组件上的 react-saga 调用函数

react-saga call function on source component

我不太确定如何正确地提出这个问题。 (对不起)基本上,当 Saga 函数出现错误时,我想在我的组件中使用错误字符串调用 onError 函数。所以我可以启动 Snackbar 5 秒,然后再次隐藏它。

但我不知道如何从我的 Saga 函数中调用这个函数。目前它 return this.state.error State as String 上的错误。我尝试使用 componentWillReceiveProps 但是当字符串仍然相同时,这在第二次尝试时不起作用。

为了避免 xy 问题,我只 post 我拥有的那段代码。

我得到了以下组件:

class RegisterForm extends React.Component {

  constructor(props) {
    super(props);
    this.state = {
      email: '',
      username: '',
      password: '',
      SnackbarOpen: false,
    };
  }
  onSubmit = (event) => {
    event.preventDefault();
    this.props.register(this.state.email, this.state.username, this.state.password);
  }

  onError(error) {
    this.setState({SnackbarOpen: true})
    setTimeout(() => {
      this.setState({SnackbarOpen: false});
    }, 5000);
  }

  render(): with <form>
}

const mapStateToProps = (state) => ({
  error: state.auth.error,
});

const mapDispatchToProps = (dispatch) => ({
  register: (email, username, password) => {
    dispatch(Actions.register(email, username, password));
  }
});

export default connect(mapStateToProps, mapDispatchToProps)(RegisterForm);

调用这个 Redux-Saga 函数:

import { Types } from './Actions';
import CognitoService from './CognitoService';

function* register(action) {
  try {
    const result = yield call(CognitoService.register, action);
    yield put({ type: Types.registrationSuccess, user: result.user });
  } catch(error) {
    yield put({ type: Types.registrationFail, error: error.message });
  }
}

function* authSaga() {
  yield takeLatest(Types.register, register);
}

export default authSaga;

在这种情况下,我看到了两种解决方案。我认为第一个更可取,使用 redux saga 通常的方法。

基于存储值呈现

在您的示例中,您在州级别保存 "SnackbarOpen" 变量。

this.setState({SnackbarOpen: true})

相反,您可以放心地存储 "register" 组件并将该变量保存在那里。所以在这种情况下,saga 会在出错时更改 store 中的那个值。简单的例子是:

 function* register(action) {
  try {
    const result = yield call(CognitoService.register, action);
    yield put({ type: Types.registrationSuccess, user: result.user });
  } catch(error) {
    yield put({ type: Types.registrationFail, error: error.message });
    yield put({ type: Types.registrationSnackBarOpen });
    yield delay(5000);
    yield put({ type: Types.registrationSnackBarClose });
  }
}

当然,将该值绑定到您的组件。

添加回调

我不建议使用这种方法,但它仍然存在。您可以只向您的操作添加回调并在 sagas 中调用它们。例如:

组件:

this.props.register(this.state.email, this.state.username, this.state.password, this.onError.bind(this);

传奇:

 function* register(action) {
  try {
    const result = yield call(CognitoService.register, action);
    yield put({ type: Types.registrationSuccess, user: result.user });
  } catch(error) {
    yield put({ type: Types.registrationFail, error: error.message });
    action.onError();
  }
}

向您的 auth reducer 添加一个 switch case 以匹配操作类型:Types.registrationFail。然后它应该提取注册的错误消息并将其分配给您的身份验证状态中的 auth.error 字段。例如

authReducer(prevState, action){
    ...
    switch(action.type){
        case Types.registrationFail: 
            return {
                ...prevState,
                error: action.error
            };
    }
    ...
}

您的组件将通过 connect(..) 函数获取商店更改。然后只需使用 componentWillReceiveProps 生命周期方法更新您的组件即可检查此消息的值。例如

componentWillReceiveProps(nextProps, nextState){
    if(nextProps.error != null && ! nextState.SnackbarOpen){
        this.onError();
    }
}

这里假设您的小吃店也在该组件内,并简单地从 this.props.error 值中提取其显示文本。否则,还有进一步清理的余地。