【发布时间】:2017-11-07 04:05:53
【问题描述】:
所以我正在使用 Redux Saga 在 React 中实现一个应用程序,我对我的特定用例的信息如此之少感到有点困惑,因为它看起来并不奇怪。很可能我使用了错误的术语或以错误的方式思考问题,因为我对 React/Redux 相当陌生。无论如何,我在谷歌上搜索这个问题的所有尝试都阻碍了我,我希望能从比我更有经验的人那里获得一些见解。
我的应用程序状态上有一个userSettings 属性,它管理登录用户的一些配置选项。在应用程序的某个时刻,用户可以翻转开关以禁用“一目了然”仪表板小部件的显示,我需要将此信息传递给后端 API 以更新他们在数据库中的设置信息,然后根据本次后端更新是否成功更新状态。
我的代码目前有一个用于所有用户设置更新的主要 saga,我打算通过一个更具体的 saga 来实现这个设置,因此:
Dashboard.js
function mapStateToProps(state) {
const { userSettings } = state;
return { userSettings };
}
...
class Dashboard extends Component {
...
...
hasDashboardAtAGlanceHiddenToggle() {
const { dispatch, userSettings } = this.props;
dispatch(setHasDashboardAtAGlanceHidden(!userSettings.hasDashboardAtAGlanceHidden));
}
}
export default connect(mapStateToProps)(Dashboard);
updateUserSettingsSaga.js
import { take, put, call } from 'redux-saga/effects';
import axios from 'axios';
import {
UPDATE_USER_SETTINGS,
SET_HAS_DASHBOARD_AT_A_GLANCE_HIDDEN,
updateUserSettings,
updatedUserSettingsSuccess
} from '../../actions';
export function* setHasDashboardAtAGlanceHiddenSaga() {
const action = yield take(SET_HAS_DASHBOARD_AT_A_GLANCE_HIDDEN);
const newValue = action.data;
//QUESTION HERE -- how to get full object to pass to updateUserSettings
yield put(updateUserSettings(stateObjectWithNewValuePopulated));
}
export default function* updateUserSettingsSaga(data) {
yield take(UPDATE_USER_SETTINGS);
try {
const response = yield call(axios.put, 'http://localhost:3001/settings', data);
yield put(updatedUserSettingsSuccess(response.data));
} catch (e) {
yield put(updatedUserSettingsFailure());
}
}
如代码中所述,我的问题是我不确定将更新值合并到状态的逻辑应该在哪里/如何发生。据我所知,我有三个选择:
-
在分发初始动作之前在组件中构建更新状态,即:
hasDashboardAtAGlanceHiddenToggle() { const { dispatch, userSettings } = this.props; const newState = Object.assign({}, userSettings , { hasDashboardAtAGlanceHidden: !userSettings.hasDashboardAtAGlanceHidden }); dispatch(setHasDashboardAtAGlanceHidden(userSettings)); }}
-
使用redux-saga的
select效果,在更具体的初始saga中构建完整的状态对象,即:export function* setHasDashboardAtAGlanceHiddenSaga() { const action = yield take(SET_HAS_DASHBOARD_AT_A_GLANCE_HIDDEN); const newValue = action.data; const existingState = select(state => state.userSettings); const updatedState = Object.assign({}, existingState, { hasDashboardAtAGlanceHidden: newValue }); yield put(updateUserSettings(updatedState)); } -
在更新之前检索服务器的用户设置对象副本,即:
export default function* updateUserSettingsSaga() { const action = yield take(UPDATE_USER_SETTINGS); try { const current = yield call(axios.get, 'http://localhost:3001/settings'); const newState = Object.assign({}, current.data, action.data); const response = yield call(axios.put, 'http://localhost:3001/settings', newState); yield put(updatedUserSettingsSuccess(response.data)); } catch (e) { yield put(updatedUserSettingsFailure()); } }
所有这些(我认为)都将作为选项起作用,但我完全不清楚在 Redux Saga 的上下文中哪种是惯用/接受/首选方法,并且令人困惑地缺乏示例(至少我已经能够找到)在与外部 API 交互时使用 POST/PUT 而不是 GET。任何帮助或指导将不胜感激 - 即使只是我以错误的方式思考这个问题。 :D
【问题讨论】:
标签: javascript reactjs redux react-redux redux-saga