2016-02-10 19 views
24

私はキーボードショートカットのサポートを私のReact/Reduxアプリにの慣用のReact/Reduxの方法でビルドしようとしています。減速が続いactionCreatorFuncReferencesへのキーコードのマッピングにReduxのストアにregisteredShortcutsオブジェクトを更新してしまう関数リファレンスをReduxストアに格納する必要がありますか?

registerShortcut(keyCode, actionCreatorFuncReference) 

:私はこれを行うことを計画しています方法は、次のアクションの作成者と関連付けられたアクションを持つことです。次に、私のルートコンポーネントはkeyupをlistenし、関連付けられたkeyCodeが登録されているかどうかを確認し、そうであれば、アクション作成者関数リファレンスを介してマップされたアクションをディスパッチします。

ただし、これは私がのReduxストアに関数参照を格納する初めてのケースです。今日まで私はバニラ値(文字列、intsなど)を持つキーを持つオブジェクトしか持っていませんでした。

Reduxのドキュメントでは、「状態をシリアライズ可能にするために最善を尽くしてください。その中にJSONを簡単に入れられないものは入れないでください。」 Reduxストアにそのような関数リファレンスを格納することは悪い考えですか?もしそうなら、私がReact/Reduxでやろうとしていることを達成する良い方法は何ですか?

代替アプローチは、ルート・リアクション・コンポーネント自体にkeyCodeと関数参照のマッピングを格納するだけですが、アプリケーション状態がReduxストアにないため、Reduxのようには感じられませんでした。

+1

私はこのようなことについて自分自身が疑問に思っています。 Redux状態は確実にシリアライズ可能である必要がありますが、時々(約束事など)あなたが周りに置いておきたいことがあります。私はちょうどhttps://github.com/rackt/redux/issues/1385でこの質問を提起 - 私たちは何かが現れたら表示されます。 – markerikson

答えて

16

いいえ、reduxストアに関数参照を格納しないでください。それらはシリアライズ可能ではなく、あなたが述べたように、状態は常にシリアライズ可能でなければなりません。私が考えることができる最も還元的なアプローチは、ホットキーのマップをactionCreatorFuncNamesに保つことです。

+0

それは興味深い考えです。どのように私は実際にactionCreatorFuncNames文字列から関数を実行するのですか? –

+1

私はあなたのアプリケーションの詳細に依存すると思います。これらのキーイベントを処理しているときは、すべてのアクションを単一の 'actions'オブジェクトにインポートするのは簡単です。難しいのは、ボタンをコンテキストに合わせて適切な引数を指定して 'actions [actionCreatorFuncNameA]'を呼び出すことです。一方、ホットキーがすべてトグルすると、引数を呼び出す必要はなく、問題は解決されます。それは理にかなっているのですか? –

+0

私はプロキシを試しています。効果的には、これはオブジェクトをシリアライズ可能にすると同時にファンクションリファレンスを持つことになります – Marc

1

私はreduxには新しいですが、私はそれを見る方法で、あなたはキーコードとアクションタイプを渡すことができます。 それから、減量兵はその行動タイプを聞いてそれに応じて変更することができます。ここで

は、ライブラリのマウストラップを使用した例です。

// On your Container 
function registerShortcut(element, dispatch, keyCode, actionType) { 
    Mousetrap(element).bind(keyCode, function(e) { 
    dispatch({ 
     type: actionType, 
     payload: { 
     keyCode: keyCode, 
     event: e 
     } 
    }); 
    }); 
}); 

mapDispatchToProps = function(dispatch) { 
    return { 
    onMount: function(element) { 
     registerShortcut(element, dispatch, ['command+f', 'ctrl+f'], 'OPEN_SEARCH'); 
    }, 
    onUnmount: function(element) { 
     Mousetrap(element).unbind(['command+f', 'ctrl+f']); 
    } 
    }; 
}; 


// On your Component 
componentDidMount() { 
    onMount(ReactDOM.findDOMNode(this)); 
}; 

componentWillUnmount() { 
    onUnmount(ReactDOM.findDOMNode(this)); 
}; 



// On your reducer 
function reducer(oldState, action)  { 
    if (action.type == 'OPEN_SEARCH') { 
    //... make changes ...// 
    return newState; 
    } 
    return oldState; 
}; 

この方法では、キーボードショートカットは、アクションを派遣します。減速機は州に必要な変更を行います。最後に、アプリケーションを再レンダリングすることができます。

0

私はreduxストアに機能を追加して本当に良い結果を出しました。関数がロジックにデータを適用するメソッドとして機能する場合は、アプリケーション全体で信じられないほど強力なものになります(JSON.stringifyは関数を削除しますので、ストアをシリアル化してローカルストレージなどに保存できます)。私は、初期状態としてクラスを使用するcurrentUserレデューサーを持っていて、currentUserが接続されているどこでも呼び出すことができるhasPermissionsメソッドを含んでいます。これは、私がcurrentUserを自分の小道具にマップするときはいつでも、何かを表示する権限を持っているかどうかを調べるために、ある種のutilをインポートすることを覚えておく必要はないからです。メソッドはすでにユーザーの上にあります。

class CurrentUser { 
    constructor() { 
     this.permissions = [] 
     this.roles = [] 
     this.admin = false 
    } 

    hasPermission = (permission) => { 
     if (this.admin) { return true } 
     if (Array.isArray(permission)) { 
     return permission.reduce((prev, curr) => { 
      if (!prev) { return false } 
      if (this.permissions.indexOf(curr) > -1) { return true } 
      return false 
     }, true) 
     } 
     return this.permissions.indexOf(permission) > -1 
    } 
    } 

    const initialState = new CurrentUser() 

    const curretUserReducer = (state = initialState, action) => { 
    const { type, payload } = action 
    switch (type) { 
     case ACTIONS.SET_CURRENT_USER: { 
     const { user } = payload 
     return Object.assign(new CurrentUser(), user) 
     } 
     case ACTIONS.CLEAR_CURRENT_USER: { 
     return new CurrentUser() 
     } 
     case ACTIONS.UPDATE_CURRENT_USER: { 
     const newCurrentUser = merge(state, payload.user) 
     storage.set('currentUser', JSON.stringify(newCurrentUser)) 
     return newCurrentUser 
     } 
     default: 
     return state 
    } 
    } 

    export default curretUserReducer 
関連する問題