在我的react-redux应用程序中,我有一个受控的文本输入.每次组件更改值时,它都会调度一个操作,最后,该值将通过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')
);
Run Code Online (Sandbox Code Playgroud)
编辑:澄清问题
Marco和Nathan都正确地指出这是React中的一个已知问题,不会被修复.如果setTimeout在onChange设置值之间存在或有其他延迟,则光标位置将丢失.
但是,setState只调度更新的事实不足以导致此错误发生.在Marco链接的Github问题中,有一条评论:
简而言之,setState不会延迟渲染,它会批量更新并在当前的React作业完成后立即执行它们,中间不会有渲染帧.因此在某种意义上,操作与当前渲染帧是同步的.setTimeout将其安排为另一个渲染帧.
这可以在JsBin示例中看到:"sync"版本也使用setState,但一切正常.
悬而未决的问题仍然是:Redux中是否存在一些延迟,允许渲染帧介于其间,或者Redux可以以避免这些延迟的方式使用?
手头的问题的解决方法是不需要的,我找到一个适用于我的情况,但我有兴趣找到更一般的问题的答案.
编辑:问题解决了
我很满意Clarks的回答甚至奖励了赏金,但事实证明,当我通过删除所有中间件来测试它时,这是错误的.我还发现了与此相关的github问题.
https://github.com/reactjs/react-redux/issues/525
答案是:
您在 Redux 应用程序中使用什么中间件?也许其中之一是在你的行动调度周围包裹着一个承诺。在没有中间件的情况下使用 Redux 不会表现出这种行为,所以我认为这可能是您的设置所特有的。