我的问题:为什么不更新我的不可变状态(Map)中的对象的属性不会导致Redux更新我的组件?Redux在深度不可变状态属性更新时没有更新组件
我试图创建一个窗口小部件,文件上传到我的服务器,我的初始状态(从我UploaderReducer里,你会看到如下图)物体看起来是这样的:
let initState = Map({
files: List(),
displayMode: 'grid',
currentRequests: List()
});
我有一个thunk方法,用于在发生事件(如进度更新)时开始上传和分派操作。例如,onProgress事件看起来是这样的:
onProgress: (data) => {
dispatch(fileUploadProgressUpdated({
index,
progress: data.percentage
}));
}
我使用redux-actions
创建和处理我的行为,所以我对于行动减速是这样的:
export default UploaderReducer = handleActions({
// Other actions...
FILE_UPLOAD_PROGRESS_UPDATED: (state, { payload }) => (
updateFilePropsAtIndex(
state,
payload.index,
{
status: FILE_UPLOAD_PROGRESS_UPDATED,
progress: payload.progress
}
)
)
}, initState);
而且updateFilePropsAtIndex
样子:
export function updateFilePropsAtIndex (state, index, fileProps) {
return state.updateIn(['files', index], file => {
try {
for (let prop in fileProps) {
if (fileProps.hasOwnProperty(prop)) {
if (Map.isMap(file)) {
file = file.set(prop, fileProps[prop]);
} else {
file[prop] = fileProps[prop];
}
}
}
} catch (e) {
console.error(e);
return file;
}
return file;
});
}
到目前为止,这一切似乎向做工精细!在Redux DevTools中,它显示为按预期的操作。但是,我的组件没有更新!添加新项目到files
阵列重新呈现我的新文件添加UI,所以终极版肯定不会有问题,我这样做......
connect
看起来连接到店里
我顶层组件像这样:
const mapStateToProps = function (state) {
let uploadReducer = state.get('UploaderReducer');
let props = {
files: uploadReducer.get('files'),
displayMode: uploadReducer.get('displayMode'),
uploadsInProgress: uploadReducer.get('currentRequests').size > 0
};
return props;
};
class UploaderContainer extends Component {
constructor (props, context) {
super(props, context);
// Constructor things!
}
// Some events n stuff...
render(){
return (
<div>
<UploadWidget
//other props
files={this.props.files} />
</div>
);
}
}
export default connect(mapStateToProps, uploadActions)(UploaderContainer);
uploadActions
是使用redux-actions
创建的操作的对象。
的files
阵列中存在file
对象基本上是这样的:
{
name: '',
progress: 0,
status
}
的UploadWidget
基本上是一个拖ñ下降DIV和一个所述files
阵列在屏幕上打印出来。
我试着用redux-immutablejs
助阵,我在GitHub上很多帖子已经看到了,但我不知道是否有帮助...这是我的根减速机:
import { combineReducers } from 'redux-immutablejs';
import { routeReducer as router } from 'redux-simple-router';
import UploaderReducer from './modules/UploaderReducer';
export default combineReducers({
UploaderReducer,
router
});
我的应用程序入口点看起来是这样的:
const store = configureStore(Map({}));
syncReduxAndRouter(history, store, (state) => {
return state.get('router');
});
// Render the React application to the DOM
ReactDOM.render(
<Root history={history} routes={routes} store={store}/>,
document.getElementById('root')
);
最后,我<Root/>
组件看起来是这样的:
import React, { PropTypes } from 'react';
import { Provider } from 'react-redux';
import { Router } from 'react-router';
export default class Root extends React.Component {
static propTypes = {
history: PropTypes.object.isRequired,
routes: PropTypes.element.isRequired,
store: PropTypes.object.isRequired
};
get content() {
return (
<Router history={this.props.history}>
{this.props.routes}
</Router>
);
}
//Prep devTools, etc...
render() {
return (
<Provider store={this.props.store}>
<div style={{ height: '100%' }}>
{this.content}
{this.devTools}
</div>
</Provider>
);
}
}
因此,最终,如果我尝试下面的状态对象更新“进步”,反应,和/终极版没有更新我的组件:
{
UploaderReducer: {
files: [{progress: 0}]
}
}
这是为什么?我认为使用Immutable.js的整个想法是,无论您更新它们的深度如何,比较修改后的对象都会更容易一些。
它似乎越来越普遍具有不可改变到Redux的工作并不简单,因为它似乎是: How to use Immutable.js with redux? https://github.com/reactjs/redux/issues/548
然而,使用不可变的吹捧好处似乎是值得这场战斗,我很乐意图我做错了什么!
UPDATE 2016年4月10日 选择的答案告诉我,我在做什么错的,为了完整起见,我updateFilePropsAtIndex
功能现在包含简单:
return state.updateIn(['files', index], file =>
Object.assign({}, file, fileProps)
);
这工作得很好! :)
当你说“的组件没有被更新“是否意味着它不会从redux中接收新的道具? mapStateToProps是否未收到更新的进度?减速机如何,动作在有效载荷中是否有正确的进展? – azium
UploaderContainer mapStateToProps函数根本不会触发,尽管在DevTools中使用期望值更新状态。我有单元测试检查我在做什么应该工作,所以我觉得在Redux级别有一些我不理解的东西,但我不知道它是什么! –
你可以在JSBin网上找到一个工作示例吗?这将更容易解决。 – whitep4nther