2017-01-13 3 views
0

Ich richte eine Redux-Anwendung ein, die einen Client erstellen muss. Nach der Initialisierung verfügt der Client über Listener und APIs, die aufgrund bestimmter Aktionen aufgerufen werden müssen.Wie wird der Client in Redux gespeichert?

Aus diesem Grund muss ich eine Instanz des Clients halten. Im Moment rette ich das im Staat. Ist das richtig?

Also habe ich die folgenden redux Aktion Ersteller, aber wenn ich eine Nachricht senden möchte, muss ich die client.say (...) API aufrufen.

Aber woher soll ich das Client-Objekt bekommen? Soll ich das Clientobjekt aus dem Status abrufen? Mein Verständnis ist, dass das ein reduziertes Anti-Muster ist. Was ist der richtige Weg, dies mit Redux zu tun?

Noch seltsamer - sollte die gesendete Nachricht als Aktionsersteller betrachtet werden, wenn sie den Status nicht tatsächlich mutiert?

Die Aktionen:

// actions.js 

import irc from 'irc'; 

export const CLIENT_INITIALIZE = 'CLIENT_INITIALIZE'; 
export const CLIENT_MESSAGE_RECEIVED = 'CLIENT_MESSAGE_RECEIVED'; 
export const CLIENT_MESSAGE_SEND = 'CLIENT_MESSAGE_SEND'; 

export function messageReceived(from, to, body) { 
    return { 
    type: CLIENT_MESSAGE_RECEIVED, 
    from: from, 
    to: to, 
    body: body, 
    }; 
}; 

export function clientSendMessage(to, body) { 
    client.say(...); // <--- where to get client from? 
    return { 
    type: CLIENT_MESSAGE_SEND, 
    to: to, 
    body: body, 
    }; 
}; 

export function clientInitialize() { 
    return (dispatch) => { 
    const client = new irc.Client('chat.freenode.net', 'react'); 

    dispatch({ 
     type: CLIENT_INITIALIZE, 
     client: client, 
    }); 

    client.addListener('message', (from, to, body) => { 
     console.log(body); 
     dispatch(messageReceived(from, to, body)); 
    }); 
    }; 
}; 

Und hier ist das Reduktions:

// reducer.js 
import { CLIENT_MESSAGE_RECEIVED, CLIENT_INITIALIZE } from '../actions/client'; 
import irc from 'irc'; 

export default function client(state: Object = { client: null, channels: {} }, action: Object) { 
    switch (action.type) { 
    case CLIENT_MESSAGE_RECEIVED: 
     return { 
     ...state, 
     channels: { 
      ...state.channels, 
      [action.to]: [ 
      // an array of messages 
      ...state.channels[action.to], 
      // append new message 
      { 
       to: action.to, 
       from: action.from, 
       body: action.body, 
      } 
      ] 
     } 
     }; 

    case CLIENT_JOIN_CHANNEL: 
     return { 
     ...state, 
     channels: { 
      ...state.channels, 
      [action.channel]: [], 
     } 
     }; 

    case CLIENT_INITIALIZE: 
     return { 
     ...state, 
     client: action.client, 
     }; 
    default: 
     return state; 
    } 
} 

Antwort

1

Verwenden Middleware das Client-Objekt in die Tat Schöpfer zu spritzen! :)

export default function clientMiddleware(client) { 
    return ({ dispatch, getState }) => { 
    return next => (action) => { 
     if (typeof action === 'function') { 
     return action(dispatch, getState); 
     } 

     const { promise, ...rest } = action; 
     if (!promise) { 
     return next(action); 
     } 

     next({ ...rest }); 

     const actionPromise = promise(client); 
     actionPromise.then(
     result => next({ ...rest, result }), 
     error => next({ ...rest, error }), 
    ).catch((error) => { 
     console.error('MIDDLEWARE ERROR:', error); 
     next({ ...rest, error }); 
     }); 

     return actionPromise; 
    }; 
    }; 
} 

es dann gelten:

const client = new MyClient(); 

const store = createStore(
    combineReducers({ 
    ... 
    }), 
    applyMiddleware(clientMiddleware(client)) 
); 

Dann können Sie es in Aktion Schöpfer verwenden:

export function actionCreator() { 
    return { 
    promise: client => { 
     return client.doSomethingPromisey(); 
    } 
    }; 
} 

Dies ist vor allem von der react-redux-universal-hot-example boilerplate project angepasst. Ich habe die Abstraktion entfernt, mit der Sie Start-, Erfolgs- und Fehleraktionen definieren können, die zum Erstellen von this abstraction in action creators verwendet werden.

Wenn Ihr Client nicht asynchron ist, können Sie diesen Code so anpassen, dass der Client übergeben wird, ähnlich wie redux-thunk in dispatch übergibt.

Verwandte Themen