// Let's say we have three events: // CONNECTED // NEW ITEM IN ARRAY // DELETED ITEM IN ARRAY // We're a doing a chat with deletion features // We have an API which is sync'd with our backend. const API = new SuperAPI() // We want constants to start const initialConnectionState = API.initialTree.connection // This is the initial tree. const initialState = { connection: API.initialTree.connection, messages: API.initialTree.messages } const CONNECTED = 'socket@@CONNECTED' const CONNECTION_ERROR = 'socket@@CONNECTION_ERROR' const DISCONNECTED = 'socket@@DISCONNECTED' const SEND_MESSAGE = 'chat@@SEND_MESSAGE' const RECEIVE_MESSAGE = 'chat@@RECEIVE_MESSAGE' const DELETE_MESSAGE = 'chat@@DELETE_MESSAGE' const RECEIVE_MESSAGE_DELETION = 'chat@@RECEIVE_MESSAGE_DELETION' // Now, actions creators const connected = createAction(CONNECTED) const disconnected = createAction(DISCONNECTED) const connectionError = createAction(CONNECTION_ERROR) const initiateConnection = () => dispatch => { return api.connect() .then(() => dispatch(connected()), error => dispatch(connectionError(error))) } const disconnect = () => dispatch => { api.disconnect() dispatch(disconnected()) } const sendMessage = message => dispatch => { api.messages.append(message) .then(() => { dispatch(messageSent(message)) }, error => dispatch(failedToSendMessage(message))) } api.on('RECEIVE_MESSAGE', message => { receiveMessage(message) }) // Reducer function reduceConnection (state = initialState.connection, action) { if (action.type === DISCONNECTED) { return { ...state, connected: false } } if (action.type === CONNECTED) { return { ...state, connected: true } } if (action.type === CONNECTION_ERROR) { return { ...state, connectionError: action.error } } return state } function reduceMessages (state = initialState.messages, action) { if (action.type === RECEIVE_MESSAGE) { return { ...state, messages: state.messages.concat([action.payload.message]) } } if (action.type === RECEIVE_MESSAGE_DELETION) { return { ...state, messages: state.messages.filter(message => message.id !== action.payload.deletedMessage.id) } } if (action.type === SENT_MESSAGE) { return { ...state, messages: state.messages.concat([action.payload.message]), messageCountSent: state.messageCountSent + 1 // This is absolutely useless, but we're doing an example. } } return state } export default combineReducers({ connection: reduceConnection, messages: reduceMessages })