【问题标题】:React component not receiving intermediate state when chaining actions in redux-saga在 redux-saga 中链接操作时,React 组件未接收到中间状态
【发布时间】:2021-03-12 08:51:34
【问题描述】:

我有两个动作 TESTTEST_DONE 在我的 redux 状态下都增加了一个 id 属性。每当我从我的组件调度第一个动作 TEST 时,我都会使用 redux-saga 自动调度第二个动作 TEST_DONE

我希望执行顺序是这样的:

  1. 组件渲染初始值为testState.id = 0
  2. 组件调度TEST动作
  3. 组件重新渲染testState.id = 1
  4. saga 调度 TEST_DONE 操作
  5. 组件重新渲染testState.id = 2

相反,我的组件仅在 testState.id 更新为 2 时重新渲染。我在getSnapshotBeforeUpdate 函数中看不到1 值。它将0 显示为前一个属性。

为什么 prop 从 0 跳转到 2 中间没有收到 1


saga.js:

export function* TestSagaFunc() {
    yield put({
        type: actions.TEST_DONE
    });
};

export default function* rootSaga() {
    yield all([
        yield takeEvery(actions.TEST, TestSagaFunc),
    ]);
};

action.js:

const actions = {
    TEST: 'TEST',
    TEST_DONE: 'TEST_DONE',

    callTest: (id) => ({
        type: actions.TEST,
        payload: {
            id
        }
    }),
};
export default actions;

reducer.js:

const initState = {
    testState:  {
        id: 0
    }
};

export default function TestReducers ( state=initState, { type, ...action}) {
    switch(type) {
    default:
        return state;
    case actions.TEST: {
        const { id } = state.testState;
        const nextId = id + 1;
        return {
            ...state,
            testState: {
                ...state.testState,
                id: nextId
            }
        };
    };
    case actions.TEST_DONE: {
        const { id } = state.testState;
        const nextId = id + 1;
        return {
            ...state,
            testState: {
                ...state.testState,
                id: nextId
            }
        };
    }
};
};

组件getSnapshotBeforeUpdate的控制台输出

【问题讨论】:

  • 如您所见,状态确实在更新,但组件渲染并不能保证在每次状态更改时都会发生。尝试从redux-saga/effectsyield delay(1000); 导入delay,然后再在TestSagaFunc 中调用yield put,这样两个状态更新就不会一起批处理。
  • @azundo 感谢您的回复,您是对的。我尝试按照您所说的进行导入,但我认为这只是一个技巧。你还有什么要彻底处理的吗?
  • 是的,这只是一个技巧。如果您需要渲染中间状态,您可以使用useEffect(或componentDidUpdate)从正在渲染的组件中分派您的第二个操作,以确保组件通过一个更新状态的渲染周期。但是没有办法强制你的组件渲染中间减速器状态,这些状态在渲染周期之间更新。
  • 那是我对 redux-saga 的了解不足。传奇帮助我们处理副作用,但我的测试不是。您分享的信息非常有帮助,我解决了我的问题。非常感谢@azundo
  • @azundo 我必须阅读这个问题和你的评论几次才能明白你在说什么。我的第一个想法是“当 redux 状态发生变化时,组件肯定会重新渲染”。但是我在这里看到我们正在谈论立即覆盖的中间更改。所以这归结为 React 如何批量更新,这不是我理解的深入到无法解释的内容。

标签: react-redux redux-saga


【解决方案1】:

从问题中总结我的cmets:

正如您所见,redux 状态确实在更新,但不能保证组件根据反应批次状态更改的方式呈现每个中间状态更改。要对此进行测试,您可以尝试从 redux-saga/effects 导入 delay 并在 yield put 中调用 yield put 之前添加 yield delay(1000); TestSagaFunc,这样两个状态更新就不会一起批处理。

这只是说明批处理效果的一个技巧,几乎可以肯定不是您想要做的。如果您需要渲染中间状态,您可以使用useEffect(或componentDidUpdate)从正在渲染的组件中分派TEST_DONE,以确保组件在中间状态下经历一个渲染周期。但是没有办法强制你的组件渲染成批处理的中间 reducer 状态。

【讨论】:

    猜你喜欢
    • 2022-01-03
    • 2019-04-01
    • 2021-11-16
    • 2018-06-26
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-09-11
    • 2017-05-03
    相关资源
    最近更新 更多