redux - react 减少 : should the render always happen in the same tick as dispatching an action?

标签 redux redux-saga

在我的 react-redux 应用程序中,我有一个受控的文本输入。每次组件更改 value 时,它​​都会调度一个 action,最后, value 通过 redux 循环返回并被渲染。

在下面的示例中,这运行良好,但在实践中,我遇到了渲染与操作调度异步发生并且输入丢失光标位置的问题。为了演示这个问题,我添加了另一个显式延迟的输入。在单词中间添加一个空格会导致光标在异步输入中跳过。

我对此有两种理论,想知道哪一种是正确的:

  • 这应该可以,但是我的生产应用程序中的某个地方有一个错误,导致延迟
  • 它在简单示例中起作用的事实只是运气,react-redux 并不能保证渲染会同步发生

  • 哪一个是对的?

    工作示例:

    http://jsbin.com/doponibisi/edit?html,js,output
    const INITIAL_STATE = {
      value: ""
    };
    
    const reducer = (state = INITIAL_STATE, action) => {
      switch (action.type) {
        case 'SETVALUE':
          return Object.assign({}, state, { value: action.payload.value });
        default:
          return state;
      }
    };
    
    const View = ({
      value,
      onValueChange
    }) => (
      <div>
        Sync: <input value={value} onChange={(e) => onValueChange(e.target.value)} /><br/>
        Async: <input value={value} onChange={(e) => { const v = e.target.value; setTimeout(() => onValueChange(v), 0)}} />
      </div>
    );
    
    const mapStateToProps = (state) => {
      return {
        value: state.value
      };
    }
    
    const mapDispatchToProps = (dispatch) => {
      return {
        onValueChange: (value) => {
          dispatch({
            type: 'SETVALUE',
            payload: {
              value
            } 
          })            
        }
      };
    };
    
    
    const { connect } = ReactRedux;
    const Component = connect(
      mapStateToProps,
      mapDispatchToProps
    )(View);
    
    const { createStore } = Redux;
    const store = createStore(reducer);
    
    ReactDOM.render(
      <Component store={store} />,
      document.getElementById('root')
    );
    

    编辑:澄清问题

    Marco 和 Nathan 都正确地指出,这是 React 中的一个已知问题,无法修复。如果有 setTimeoutonChange 之间的其他延迟并设置该值,光标位置将丢失。

    但是,setState 只是安排更新这一事实不足以导致此错误发生。在 Github issue Marco 链接,有一条评论:

    Loosely speaking, setState is not deferring rendering, it's batching updates and executing them immediately when the current React job has finished, there will be no rendering frame in-between. So in a sense, the operation is synchronous with respect to the current rendering frame. setTimeout schedules it for another rendering frame.



    这可以在 JsBin 示例中看到:“同步”版本也使用 setState,但一切正常。

    悬而未决的问题仍然是:Redux 内部是否有什么东西会产生延迟,让渲染帧介于两者之间,或者是否可以以一种避免这些延迟的方式使用 Redux?

    不需要解决手头问题的解决方法,我找到了一个适用于我的情况的解决方法,但我有兴趣找出更普遍问题的答案。

    编辑:问题已解决

    我对 Clarks 的回答很满意,甚至还获得了赏金,但当我通过删除所有中间件来真正测试它时,事实证明这是错误的。我还发现了与此相关的 github 问题。

    https://github.com/reactjs/react-redux/issues/525

    答案是:
  • 这是 react-redux 中的一个问题,将在 react-redux 5.1 和 react v16
  • 中修复

    最佳答案

    您在 Redux 应用程序中使用什么中间件?也许其中一个是在你的 Action 调度周围包装一个 promise 。在没有中间件的情况下使用 Redux 不会表现出这种行为,所以我认为这可能是您的设置所特有的。

    关于redux - react 减少 : should the render always happen in the same tick as dispatching an action?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/42436068/

    相关文章:

    angular - 如何规范化 ngrx/store 中的深层嵌套数据?

    javascript - Redux:当从数组中删除特定元素时,它会删除最后一个元素

    javascript - 如何使用 redux saga 将 ID 传递给 API 调用?

    reactjs - redux 中的选择器是什么?

    javascript - Redux 传奇路由器。如何在每场比赛中运行特定的路线传奇?

    javascript - Redux 中的 React Router 路由参数

    javascript - 为什么 redux store/state 更新时 mergeProps 中使用的函数不更新?

    javascript - Redux 状态在我访问它时没有更新

    javascript - 如何从 redux-saga 函数中的状态/存储中获取某些东西?

    javascript - React-boilerplate 将 sagas 注入(inject)路由