React / Redux connect不会在商店更改

时间:2016-10-12 17:29:59

标签: javascript reactjs redux

我遇到了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.onlinetrue。一切正常,Redux开发工具显示商店正确更新,现在在线是真的。如果我查看React dev工具Connect(AppClass)组件,它的storeState是最新的,但它的子组件AppClass没有正确的道具,this.props.app.connection.online是假的,它应该是真正。我已经看到它可能来自状态变异,但是使用Object.assign返回一个新的存储(函数是MDN Polyfill)。

希望我很清楚,谢谢你!

(注意我使用的是Typescript进行编译,虽然我可能忽略了一些接口定义)

2 个答案:

答案 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}