我遇到了Redux的问题(与React一起使用)。这是我的代码:
/// <reference path="../../typings/index.d.ts"/>
import "./polyfill.ts";
import * as React from 'react'
import * as ReactDOM from 'react-dom'
import { createStore, combineReducers } from 'redux'
import { Provider, dispatch } from 'react-redux'
import { Router, Route, browserHistory, IndexRedirect } from 'react-router'
import { syncHistoryWithStore, routerReducer } from 'react-router-redux'
import { Form, Input } from './components/form.tsx'
import app from './reducers.ts'
const store = createStore(
combineReducers({
app,
routing: routerReducer
}),
{},
window.devToolsExtension && window.devToolsExtension()
);
import App from './views/app.tsx';
import Reminders from './views/reminders.tsx';
import Calendar from './views/calendar.tsx';
import Settings from './views/settings.tsx';
import Groups from './views/groups.tsx';
import Courses from './views/courses.tsx';
import Homework from './views/homework.tsx';
// Create an enhanced history that syncs navigation events with the store
const history = syncHistoryWithStore(browserHistory, store);
class Application extends React.Component<any,any> {
constructor(props){
super(props);
}
render() {
var socket = io();
socket.on('connect', function () {
setTimeout(function(){
store.dispatch({
type: "SOCKET_ESTABLISHED",
socket: socket
});
}, 1000);
});
socket.on('DATA', function(data){
console.log("DATA");
console.log(data);
})
console.log(Groups);
return <Provider store={store}>
<Router history={history}>
<Route path="/" component={App}>
<IndexRedirect to="/reminders" />
<Route path="reminders" component={Reminders}/>
<Route path="calendar" component={Calendar}/>
<Route path="settings" component={Settings}>
<Route path="groups" component={Groups}/>
</Route>
<Route path="homework" component={Homework} />
</Route>
</Router>
</Provider>
}
}
ReactDOM.render(
<Application/>,
document.getElementById('mount')
);
我的reducer文件如下所示:
export default function app(state={
connection: {
socket: null,
online: false
}
}, action: any) {
console.log(action);
switch(action.type){
case "SOCKET_ESTABLISHED":
console.log(state.connection);
return Object.assign(state, {
connection: {
socket: action.socket,
online: true
}
});
default:
return state;
}
};
我的App组件如下:
import * as React from 'react';
import { connect } from 'react-redux';
import Top from '../components/top.tsx';
import Nav from '../components/nav.tsx';
class AppClass extends React.Component<any,any> {
constructor(props){
super(props);
}
render() : JSX.Element {
return <div>
<Top/>
<Nav/>
{this.props.connection.online ? this.props.children : "Offline." }
</div>
}
}
var App = connect(function(state){
return {
connection: state.app.connection
};
})(AppClass);
export default App;
所以让我说清楚,我正在使用connect函数来同步商店和App道具。页面加载时,会创建一个套接字连接,并将操作SOCKET_ESTABLISHED更改为store.connection.online
到true
。一切正常,Redux开发工具显示商店正确更新,现在在线是真的。如果我查看React dev工具Connect(AppClass)
组件,它的storeState是最新的,但它的子组件AppClass没有正确的道具,this.props.app.connection.online
是假的,它应该是真正。我已经看到它可能来自状态变异,但是使用Object.assign返回一个新的存储(函数是MDN Polyfill)。
希望我很清楚,谢谢你!
(注意我使用的是Typescript进行编译,虽然我可能忽略了一些接口定义)
答案 0 :(得分:1)
您正在修改reducer内的状态对象。您需要将状态复制到新对象,然后修改新对象。
更新此内容:
return Object.assign(state, {
connection: {
socket: action.socket,
online: true
}
});
对此:
return Object.assign({}, state, {
connection: {
socket: action.socket,
online: true
}
});
// or this
return {
...state,
connection: {
socket: action.socket,
online: true
}
}
Redux从reducer接收新状态并将其与之前的状态进行比较。如果直接修改状态,则新状态和先前状态是相同的对象。它与此类似。
var state = { foo: 'bar' };
state.test = 'test';
var newState = state;
// state === newState # true
相反,您希望在修改
之前复制对象var state = { foo: 'bar' };
var newState = { ...state, test: 'test' };
// state === newState # false
答案 1 :(得分:0)
mapStateToProps函数必须返回新的状态对象以重新呈现组件。
尝试更改
return state
到
return {...state}