- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
所以我正在使用 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());
}
}
如代码中所述,我的问题是我不确定将更新值合并到状态中的逻辑应该在何处发生/如何发生。据我所知,我有三个选择:
在分派(dispatch)初始操作之前在组件中构建更新状态,即:
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
最佳答案
GET/PUT/POST
方面与问题无关。总的来说,你的问题真的归结为 the frequently asked question "How do I split logic between action creators and reducers?" .引用那个答案:
There's no single clear answer to exactly what pieces of logic should go in a reducer or an action creator. Some developers prefer to have “fat” action creators, with “thin” reducers that simply take the data in an action and blindly merge it into the corresponding state. Others try to emphasize keeping actions as small as possible, and minimize the usage of getState() in an action creator. (For purposes of this question, other async approaches such as sagas and observables fall in the "action creator" category.)
There are some potential benefits from putting more logic into your reducers. It's likely that the action types would be more semantic and more meaningful (such as "USER_UPDATED" instead of "SET_STATE"). In addition, having more logic in reducers means that more functionality will be affected by time travel debugging.
This comment sums up the dichotomy nicely:
Now, the problem is what to put in the action creator and what in the reducer, the choice between fat and thin action objects. If you put all the logic in the action creator, you end up with fat action objects that basically declare the updates to the state. Reducers become pure, dumb, add-this, remove that, update these functions. They will be easy to compose. But not much of your business logic will be there. If you put more logic in the reducer, you end up with nice, thin action objects, most of your data logic in one place, but your reducers are harder to compose since you might need info from other branches. You end up with large reducers or reducers that take additional arguments from higher up in the state.
我还写了my own thoughts on "thick and thin reducers"不久前。
因此,归根结底,这取决于您更喜欢如何构建逻辑。
关于javascript - 使用 Redux Saga 更新单个状态属性的最佳实践,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/47149807/
有什么方法可以将来自 node_modules 的 sagas 与我为我的应用程序编写的其他 sagas 结合起来吗?如果 sagaMiddleware.run() 接受 sagas 数组,但 id
我熟悉redux-thunk,今天来redux-saga,我知道当我们要处理异步的时候,redux-saga需要先调用一个actions作为signal,然后sagas来处理,返回成功/失败操作,所以
如果我有两个 sagas 在同一 Action 上等待 yield take(),是否可以保证哪个 saga 将首先选择该 Action 并执行其剩余逻辑或者是随机的?我需要确保第一个传奇在第二个传奇
我一直在关注 AxonBank example为了理解 Axon 框架中 Saga 的实现,并有一些像这样的代码来开始和结束 saga @Saga public class MoneyTransfer
我有一个基本的传奇,如下所示: const mySaga = function* () { yield takeEvery("SOME_ACTION_REQUEST", function* (
关闭。这个问题是not reproducible or was caused by typos .它目前不接受答案。 这个问题是由于错别字或无法再重现的问题引起的。虽然类似的问题可能是on-topi
我正在开发一个使用 redux-saga 的项目管理来自 API 调用的状态更改。 我看过很多关于如何对传奇进行单元测试的例子,但很少有例子可以用来实际进行集成测试。我们正在使用 jest对于断言。
我有下一个代码: const sagaMiddleware = createSagaMiddleware(options); . . . const createdStore = createStor
当调度一个 Action 时,它到达 reducer 和传奇的顺序是否得到保证? 我可以信赖它 首先进入reducer 那么传奇呢? reducer : function reducer(state
我们的应用程序使用尝试 - 成功 - 失败的方法来处理来自服务器的响应。 我有一个生成器函数,需要像这样运行: function * getSingleSectorAttempt(action) {
当它在屏幕上可见时,我正在记录横幅展示次数。 当用户滚动时,同一条横幅可以在短时间内多次显示。 我想防止这种情况发生。 乍一看,throttle是防止它的完美方法。 但是,当您在一页中有多个横幅时,t
我在 containers/App/sagas.js 中有一个 sagas.js,它包含一个登录 saga,我试图从一个登录弹出窗口调用它,它也有自己的 sagas.js (components/Lo
我有一个 Saga,我需要在其中执行 3 个异步请求,然后在后续请求中使用这 3 个请求的响应。这里有一些伪代码来解释: function* useOtherActionsAndSagas(actio
所以,我是 react 样板的新手,似乎没有办法在不影响前一个传奇的功能的情况下包含另一个传奇(即它不起作用)。 我尝试将 sagas 声明为常量,然后将其传递到容器末尾的 compose 函数中,但
我有以下情况: export function* addCircle(circleApi, { payload }) { try { const response = yiel
以前也有人问过类似的问题,但答案对我没有任何帮助。 What are selectors in redux? How to get something from the state / store i
我有一个运行良好的传奇,我调用一个操作并包含一些数据,传奇被触发,它从操作中提取值,执行API调用并以几个yield put结束 - 太棒了。 我现在正在尝试测试该传奇并解决问题,我已经编写了一个简单
我使用 redux-saga 的主要原因之一是它进行异步函数调用的可测试性。我的困境是,当我使用不属于我的 redux 存储的有状态对象进行编程时,使用 sagas 进行编程变得非常尴尬。是否有使用非
我是传奇世界的新手。虽然我在 react-native 领域使用过 thunk,但此刻我很困惑。我正在努力让我的项目的骨架继续运行,我希望它很快就会变得非常大。考虑到这一点,我试图将逻辑分成多个文件。
我正在使用 saga eventChannel 来监听正在触发的事件(可能是实际应用程序中的 WebSocket),然后我正在更新我的 Redux Store。在组件中,我正在调用 API 操作。然后
我是一名优秀的程序员,十分优秀!