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

时间:2017-09-09 12:02:07

标签: reactjs react-redux redux-saga

我很不确定如何正确地问这个问题。 (对不起)基本上我想在Saga函数出错时用Error String调用Component中的 onError 函数。所以我可以点燃Snackbar 5秒然后再次隐藏它。

但我不知道我可以从佐贺功能中调用这个函数。目前,它将this.state.error状态的错误作为字符串返回。我尝试使用componentWillReceiveProps但是当字符串仍然相同时,这在第二次尝试时不起作用。

为了避免出现问题,我只会发布我所拥有的代码。

我得到了以下组件:

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;

2 个答案:

答案 0 :(得分:3)

auth缩减器中添加一个开关案例,以匹配操作类型: Types.registrationFail 。然后,它应该提取已注册的错误消息并将其分配给身份验证状态中的auth.error字段。 e.g。

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

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

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

在此假设您的快餐栏也在此组件中,并简单地从this.props.error值中提取其显示文本。否则,可以进一步清理它。

答案 1 :(得分:1)

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

根据商店值进行渲染

在您的示例中,您可以保存&#34; SnackbarOpen&#34;国家层面的变量。

this.setState({SnackbarOpen: true})

相反,你可以为&#34;注册&#34;组件并在那里保存该变量。所以在这种情况下,saga会在出错时更改商店中的值。简单的例子是:

 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 });
  }
}

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

添加回调

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

组件:

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();
  }
}