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


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

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


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

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


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

@ -8,7 +8,10 @@ import SocketStatusPane from "../components/SocketStatusPane";
const Footer = ({ login, socket }) => { const Footer = ({ login, socket }) => {
return ( return (
<footer> <footer>
<SocketStatusPane {...socket} />
<SocketStatusPane
state={socket.get("state")}
url={socket.get("url")}
/>
<LoginStatusPane <LoginStatusPane
status={login.get("status")} status={login.get("status")}
username={login.get("username")} username={login.get("username")}
@ -20,8 +23,8 @@ const Footer = ({ login, socket }) => {
}; };
Footer.propTypes = { Footer.propTypes = {
login: ImmutablePropTypes.map.isRequired,
socket: PropTypes.object.isRequired
login: ImmutablePropTypes.map.isRequired,
socket: ImmutablePropTypes.map.isRequired
}; };
const mapStateToProps = ({ socket, login }) => ({ socket, login }); 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 createRoutes = (store) => {
const requireLoggedIn = (nextState, replaceState) => { const requireLoggedIn = (nextState, replaceState) => {
let { socket, login } = store.getState(); let { socket, login } = store.getState();
if (socket.state !== STATE_OPEN ||
if (socket.get("state") !== STATE_OPEN ||
login.get("status") !== LOGIN_STATUS_SUCCESS) login.get("status") !== LOGIN_STATUS_SUCCESS)
{ {
replaceState({}, "/"); replaceState({}, "/");


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

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