我使用 redux-saga 从服务器获取数据以进行异步操作。我可以获取数据,但我认为我没有效率。因为我的EMAIL_SERVICE_FETCH_SUCCESS
动作多次运行。在给出一个例子之前,我想澄清一下我的应用程序结构。
AdminDashboard(admin / dashboard) - 具有的父组件 SideNavigation和Routes组件作为子项。
SideNavigation有链接,点击后会显示数据 页面中间,旁边是SideNavigation。
现在问题。当我去route / admin / dashboard / email_service时,我得到了我期待的数据。之后如果我点击其他一些链接并返回到email_service,那么成功动作会被多次触发,并且会继续增加,增加和增加。
index.js
const mapDispatchToProps = dispatch => ({
fetchEmailService: () => dispatch(fetchEmailService())
});
const mapStateToProps = createStructuredSelector({
email: selectEmailService()
});
class EmailService extends React.PureComponent {
state = {
emailService: {
api_key: "",
domain: ""
},
};
componentDidMount() {
this.props.fetchEmailService();
}
componentWillReceiveProps(nextProps, prevProps) {
if (nextProps.email) {
nextProps.email
.entrySeq()
.map(([key, value]) => {
this.setState(state => ({
emailService: { ...state.emailService, [key]: value }
}));
})
.toArray();
}
}
render() {
const { emailService, errors } = this.state;
const { email } = this.props;
if (email.size === 0) {
return <div>fetching...</div>;
}
return (
<form onSubmit={this.handleSubmit}>
<TextFieldGroup
name="api_key"
type="text"
value={emailService.api_key}
onChange={this.handleChange}
error={errors.api_key}
/>
<TextFieldGroup
name="domain"
type="text"
value={emailService.domain}
onChange={this.handleChange}
onBlur={this.handleBlur}
/>
<button className="btn btn-primary">Save Changes</button>
</form>
);
}
}
export default connect(mapStateToProps, mapDispatchToProps)(EmailService);
reducer.js
function emailServiceState(state = initialState, action) {
switch (action.type) {
case EMAIL_SERVICE_FETCH_REQUEST:
return state.set("requesting", true).set("successful", false);
case EMAIL_SERVICE_FETCH_SUCCESS:
return state.set("successful", true).set("emailService", fromJS(action.emailService.data));
case EMAIL_SERVICE_FETCH_FAILURE:
return state.set("error", action.error);
default:
return state;
}
}
selectors.js
export const selectEmailService = () => state =>
state.getIn(["emailService", "emailService"]);
sagas.js
function* fetchemailService(action) {
yield call(
EmailApi.get(
"api/configuration/email-service",
emailServiceFetched,
emailServiceFetchingError
)
);
}
function* emailServiceWatcher() {
yield takeLatest(EMAIL_SERVICE_FETCH_REQUEST, fetchemailService);
}
export default [emailServiceWatcher];
答案 0 :(得分:1)
好的,我看了你的回购,我找到了问题:
这是EmailService/sagas.js
内的代码,请查看我添加的评论。
function* setupemailService(action) {
const successWatcher = yield fork(redirectOnSuccess);
yield fork(...);
// 1. On LOCATION_CHANGE you are only cancelling the `successWatcher`
yield take([LOCATION_CHANGE, EMAIL_SERVICE_SETUP_FAILURE]);
yield cancel(successWatcher);
}
function* emailServiceWatcher() {
yield takeLatest(EMAIL_SERVICE_SETUP_REQUEST, setupemailService);
// 2. you never cancelled `EMAIL_SERVICE_FETCH_REQUEST` watcher
yield takeLatest(EMAIL_SERVICE_FETCH_REQUEST, fetchemailService);
}
export default [emailServiceWatcher];
你需要做的是这样的事情
function* emailServiceWatcher() {
const setupeWatcher = yield takeLatest(EMAIL_SERVICE_SETUP_REQUEST, setupemailService);
const fetchWatcher = yield takeLatest(EMAIL_SERVICE_FETCH_REQUEST, fetchemailService);
// Cancel these watchers on LOCATION_CHANGE
yield take([LOCATION_CHANGE]);
yield cancel(setupeWatcher);
yield cancel(fetcheWatcher);
}