如何在 Cordova 中使用 redux 正确初始化 React 应用程序 - 未调用 mapStateToProps

How to properly initialize React app with redux in Cordova - mapStateToProps not called

我有一个用 React + Redux 实现的游戏试点,它在普通浏览器(网络版)中工作得很好。

当 运行 Cordova(这是最终目标)时,它会在 reducer 处理完数据(来自服务器的令牌)后立即停止。状态更改未传递到已连接容器中的 mapStateToProps 方法。在网络版中,它就像一个魅力。

似乎 "connect" 还没有完成……不知何故。 reducer 完成工作后不会调用 mapStateToProps,但这只会在 Cordova 中 运行 时发生!

我怀疑问题是在应用程序启动时一直出现的。我已经研究并搜索了强制等待 'deviceready' 事件的变体。这是我的 index.jsx 代码:

import React from "react";
import ReactDOM from "react-dom";
import {Provider} from "react-redux";
import {Router, Route, IndexRoute, useRouterHistory, hashHistory} from   "react-router";
import {createHashHistory} from "history";
import App from "./components/app";
import Game from "./components/game";
import Frontpage from "./components/frontpage";
import {store} from "./store";

function startApp() {
  ReactDOM.render(
    <Provider store={store}>
      <Router history={hashHistory}>
        <Route path="/" component={App}>
          <IndexRoute component={Frontpage}/>
          <Route path="game" component={Game}/>
        </Route>
      </Router>
    </Provider>
    , document.querySelector('.my-container')
  );
}

const url = document.URL;
const isSmart = (url.indexOf("http://") === -1 && url.indexOf("https://")     === -1);
const isRipple = (url.indexOf(":3000") !== -1);

if (isSmart || isRipple) {
  document.addEventListener('deviceready', startApp, false);
} else {
  startApp();

}

"troublesome" 容器如下所示 (frontpage.js):

import React, {Component} from "react";
import {connect} from "react-redux";
import * as actions from "../actions";
import {hashHistory} from "react-router";

class Frontpage extends Component {

  componentWillMount() {
    if (this.props.token) {
      hashHistory.push("/game");
    } else {
      this.props.fetchToken(this.props.handleMessageFromChannel);
    }
  }

  componentWillUpdate(nextProps) {
    if (nextProps.token) {
      hashHistory.push("/game");
    }
  }

  render() {
    return <div className="frontpage"></div>
  }
}

function mapStateToProps(state) {
  return { token: state.token };
}

export default connect(mapStateToProps, actions)(Frontpage);

商店定义在store.js:

import reducers from "./reducers/index";
import ReduxPromise from "redux-promise";
import {createStore, applyMiddleware} from "redux";

export const store = applyMiddleware(ReduxPromise)(createStore)(reducers);

文件中的 token reducer token_reducer.js:

import {FETCH_TOKEN} from "../actions/types";

export default function (state = null, action) {
  switch (action.type) {
    case FETCH_TOKEN:
      return action.payload.data.token;
  }

  return state;
}

从 Google 和 SO 搜索中,我找不到有同样问题的人。 如果相关,我很乐意 post 更多文件...?

错误出在其他地方...

其中一个减速器卡住了——或者失败了——导致动作处理停止。控制台中没有警告或错误,因此很难查明问题所在。

为什么在 Cordova 上有不同的行为? 另一个减速器创建一个 EventSource 对象(用于接收服务器发送的事件)并且根据 "school book patterns" 我创建它所以它会使用原始协议,无论是 https 还是 http:

const eventSource = new EventSource("//192.168.1.2:8080/api/channel...);
eventSource.onmessage = function(message) {
  store.dispatch(handleMessageFromChannel(message.data))
};

但是这在Cordova上玩的不好,因为加载的JavaScript的协议是file://,显然建立EventSource是错误的到设备的文件系统。

正确的代码应该是:

const eventSource = new EventSource("http://192.168.1.2:8080/api/channel...);
eventSource.onmessage = function(message) {
  store.dispatch(handleMessageFromChannel(message.data))
};

...对于生产来说,这将是一个合适的 URL,最好是 https。