Browse Source

Make socket reducer state immutable.

pull/1/head
Titouan Rigoudy 9 years ago
parent
commit
fa9ac65436
7 changed files with 38 additions and 38 deletions
  1. +11
    -5
      src/components/ConnectForm.js
  2. +1
    -2
      src/components/SocketStatusPane.js
  3. +1
    -1
      src/containers/ConnectPage.js
  4. +6
    -3
      src/containers/Footer.js
  5. +1
    -1
      src/createRoutes.js
  6. +18
    -15
      src/reducers/socket.js
  7. +0
    -11
      src/reducers/solstice.js

+ 11
- 5
src/components/ConnectForm.js View File

@ -1,5 +1,6 @@
import React, {PropTypes} from "react";
import {reduxForm} from "redux-form";
import ImmutablePropTypes from "react-immutable-proptypes";
import SocketStatusPane from "./SocketStatusPane";
import { STATE_CLOSED } from "../constants/socket";
@ -11,26 +12,31 @@ const ConnectForm = (props) => {
return actions.socket.open(values.url, actions.socketHandlers);
});
const isSocketClosed = socket.get("state") === STATE_CLOSED;
return (
<div id="connect-form">
<h2>Connect to a solstice client</h2>
<form onSubmit={onSubmit}>
<input type="url" defaultValue="ws://localhost:2244" {...url}
required pattern="wss?://.+"/>
<button type="submit" disabled={socket.state !== STATE_CLOSED}>
<button type="submit" disabled={!isSocketClosed}>
Connect
</button>
</form>
<SocketStatusPane {...socket} />
<SocketStatusPane
state={socket.get("state")}
url={socket.get("url")}
/>
</div>
);
};
ConnectForm.propTypes = {
fields: PropTypes.object.isRequired,
fields: PropTypes.object.isRequired,
handleSubmit: PropTypes.func.isRequired,
socket: PropTypes.object.isRequired,
actions: PropTypes.object.isRequired
socket: ImmutablePropTypes.map.isRequired,
actions: PropTypes.object.isRequired
};
export default reduxForm({


+ 1
- 2
src/components/SocketStatusPane.js View File

@ -4,8 +4,7 @@ import {
STATE_OPENING, STATE_OPEN, STATE_CLOSING, STATE_CLOSED
} from "../constants/socket";
const SocketStatusPane = (props) => {
const { state, url } = props;
const SocketStatusPane = ({ state, url }) => {
let string;
switch (state) {
case STATE_OPENING:


+ 1
- 1
src/containers/ConnectPage.js View File

@ -31,7 +31,7 @@ class ConnectPage extends React.Component {
getLoginStatusOrRedirect(props) {
const { actions, login, router, socket } = props;
if (socket.state === STATE_OPEN)
if (socket.get("state") === STATE_OPEN)
{
const loginStatus = login.get("status");
switch (loginStatus) {


+ 6
- 3
src/containers/Footer.js View File

@ -8,7 +8,10 @@ import SocketStatusPane from "../components/SocketStatusPane";
const Footer = ({ login, socket }) => {
return (
<footer>
<SocketStatusPane {...socket} />
<SocketStatusPane
state={socket.get("state")}
url={socket.get("url")}
/>
<LoginStatusPane
status={login.get("status")}
username={login.get("username")}
@ -20,8 +23,8 @@ const Footer = ({ login, socket }) => {
};
Footer.propTypes = {
login: ImmutablePropTypes.map.isRequired,
socket: PropTypes.object.isRequired
login: ImmutablePropTypes.map.isRequired,
socket: ImmutablePropTypes.map.isRequired
};
const mapStateToProps = ({ socket, login }) => ({ socket, login });


+ 1
- 1
src/createRoutes.js View File

@ -12,7 +12,7 @@ import { LOGIN_STATUS_SUCCESS } from "./constants/login";
const createRoutes = (store) => {
const requireLoggedIn = (nextState, replaceState) => {
let { socket, login } = store.getState();
if (socket.state !== STATE_OPEN ||
if (socket.get("state") !== STATE_OPEN ||
login.get("status") !== LOGIN_STATUS_SUCCESS)
{
replaceState({}, "/");


+ 18
- 15
src/reducers/socket.js View File

@ -1,3 +1,5 @@
import Immutable from "immutable";
import * as types from "../constants/ActionTypes";
import {
STATE_OPENING, STATE_OPEN, STATE_CLOSING, STATE_CLOSED
@ -5,14 +7,14 @@ import {
import ControlRequest from "../utils/ControlRequest";
const initialState = {
const initialState = Immutable.Map({
state: STATE_CLOSED
};
});
export default (state = initialState, { type, payload }) => {
const sendRequest = (controlRequest) => {
try {
state.socket.send(JSON.stringify(controlRequest));
state.get("socket").send(JSON.stringify(controlRequest));
} catch (err) {
console.log(`Socket error: failed to send ${controlRequest}`);
}
@ -21,37 +23,38 @@ export default (state = initialState, { type, payload }) => {
switch (type) {
case types.SOCKET_SET_OPENING:
{
if (state.state !== STATE_CLOSED) {
if (state.get("state") !== STATE_CLOSED) {
console.log("Cannot open socket, already open");
return state;
}
const { url, onopen, onclose, onerror, onmessage } = payload;
const socket = new WebSocket(url);
socket.onopen = onopen;
socket.onclose = onclose;
socket.onerror = onerror;
socket.onmessage = onmessage;
return {
...state,
state: STATE_OPENING,
socket,
url
};
return state
.set("state", STATE_OPENING)
.set("socket", socket)
.set("url", url);
}
case types.SOCKET_SET_OPEN:
return { ...state, state: STATE_OPEN };
return state.set("state", STATE_OPEN);
case types.SOCKET_SET_CLOSING:
// Ooh bad stateful reducing...
state.socket.close();
return { ...state, state: STATE_CLOSING };
state.get("socket").close();
return state.set("state", STATE_CLOSING);
case types.SOCKET_SET_CLOSED:
return { ...state, state: STATE_CLOSED };
return state.set("state", STATE_CLOSED);
case types.SOCKET_SET_ERROR:
console.log("Socket error");
return { ...state, state: state.socket.readyState };
return state.set("state", state.get("socket").readyState);
case types.LOGIN_GET_STATUS:
sendRequest(ControlRequest.loginStatus());


+ 0
- 11
src/reducers/solstice.js View File

@ -1,11 +0,0 @@
import objectAssign from 'object-assign';
const initialState = {
socketConnected: false,
clientConnected: false,
loggedIn: false
};
export default function solsticeAppState(state = initialState, action) {
return state;
}

Loading…
Cancel
Save