【问题标题】:React/Redux connect does not fire mapStateToProps on store changeReact/Redux 连接不会在存储更改时触发 mapStateToProps
【发布时间】:2017-07-11 06:11:01
【问题描述】:

我在使用 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;

所以让我明确一点,我正在使用连接功能来同步商店和应用道具。页面加载后,会创建一个套接字连接,并且操作 SOCKET_ESTABLISHED 将 store.connection.online 更改为 true。一切正常,Redux 开发工具显示商店已正确更新,现在在线是真的。如果我使用 React 开发工具查看 Connect(AppClass) 组件,它的 storeState 是最新的,但它的子组件,即 AppClass,没有正确的 props,this.props.app.connection.online 在应该为 true 的地方是 false。我已经看到它可能来自状态突变,但是使用 Object.assign 会返回一个新存储(函数是 MDN Polyfill)。

希望我说得清楚,谢谢!

(请注意,我使用 Typescript 进行编译,尽管我可能忽略了一些接口定义)

【问题讨论】:

    标签: javascript reactjs redux


    【解决方案1】:

    您正在修改减速器内部的状态对象。您需要将状态复制到新对象,然后修改新对象。

    更新这个:

    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
    

    【讨论】:

      【解决方案2】:

      mapStateToProps 函数必须返回新的状态对象以触发组件的重新渲染。

      尝试改变

      return state
      

      return {...state} 
      

      【讨论】:

      • 实际上 Typescript 不会正确编译三点运算符,因此我将使用明确的对象命名来更新我的问题。无论如何,谢谢你的帮助!
      猜你喜欢
      • 2018-02-21
      • 1970-01-01
      • 1970-01-01
      • 2020-07-13
      • 1970-01-01
      • 1970-01-01
      • 2019-11-10
      • 2019-03-11
      • 1970-01-01
      相关资源
      最近更新 更多