2017-06-21 7 views
1

私は現在ReduxとReactを学んでいます。私はこのような働きをする趣味プロジェクトを書いています。URLハッシュとRedux状態の双方向バインド

プロジェクトはタグで検索する検索サービスです。ユーザーはUIでタグを追加または削除できます。コードでは、タグはRedux状態で表され、タグの追加と削除は別々のアクションによって行われます。これまでのところとても良いですし、私は働くおもちゃのコードを持っています。

ここで、どういうわけか、タグをURLのハッシュの後ろに「バインド」したいと思います。たとえば、タグをダッシュ​​で区切ってシリアル化します。ユーザーはURLをコピー/ペーストして同じタグを持つことができます。

私はそれを簡単に行う方法が見つかりません。

私はいつも「反応ルータ」と呼ばれるものにぶつかっていますが、例では、常にアプリケーションへの入力ポイントが増え、ハッシュに従ってアプリケーションのさまざまな部分を表示しています。私はそれを望んでいない。だから私は実際にこのルータが必要かどうかわかりません。私は何かをルートしたくない。

私がこれを望む場合でも、私はRedux状態をURLにバインドする方法を見つけることができません。私はタグを部品の小道具に直接注入したくない。私は、Redux状態のURLからタグを取得したい。

私は間違ったことをしているように感じています。私は全体のデザインを再考する必要がありますが、どこから始めるべきかはわかりません。

(私はそれがアプリの設計に関する一般的な質問だと思うので、私は、任意の実際のコードを追加しませんでしたが、私は後で私のおもちゃのコードを簡素化し、それをここに貼り付けることができます)

答えて

1

あなたはなhashchangeイベントやアップデートに耳を傾ける必要があります一度それが変わった状態。双方向バインディングを実行するには、状態の変更を聞き、状態が変更されたらウィンドウハッシュを更新する必要もあります。 - エンハンサー、ハッシュ<の2ウェイバインディング作る - >ストア私はアレキサンダーBykovの答え+ Reduxの-存続に触発され、これを作った

function changeHash(state = '', action) { 
    if(action.type == 'CHANGE_HASH') 
    return action.hash; 

    return state; 
} 

const store = Redux.createStore(changeHash); 

store.subscribe(() => { 
    const hash = store.getState(); 
    if (window.location.hash !== hash) { 
    window.location.hash = hash; 
    console.log('State changed: ' + hash); 
    } 
}); 

window.addEventListener("hashchange",() => { 
    const hash = window.location.hash; 
    if (store.getState() !== hash) { 
    store.dispatch({ 
     type: 'CHANGE_HASH', 
     hash 
    }); 
    console.log('Hash changed: ' + hash); 
    } 
}, false); 

setTimeout(() => { 
    store.dispatch({ 
    type: 'CHANGE_HASH', 
    hash: '#changed-state' 
    }); 
}, 3000); 

setTimeout(() => { 
    window.location.hash = '#changed-hash'; 
}, 6000); 
+0

このサンプルもreact-router-reduxで確認してくださいhttps://fiddle.jshell.net/omerts/r9dbgsjj/ –

+0

サンプルは最新の反応ルータでは動作しません –

+0

同じように機能するエンハンサを作成しましたが、私はそこで最も重要な部分をコピーしてからあなたの答えを選択します –

0

:これは、働くことができる方法のアイデア(fiddle)であります。このような

import { applyMiddleware } from 'redux'; 
import createActionBuffer from 'redux-action-buffer'; 

const CHANGE_HASH = '@@hashSynch/CHANGE_HASH'; 
const hashEnhancer = (hashFromState, stateFromStateAndHash) => createStore => (reducer, initialState) => { 
    const store = createStore(liftReducer(reducer), initialState, applyMiddleware(createActionBuffer(CHANGE_HASH))); 
    store.subscribe(() => { 
    const hash = hashFromState(store.getState()); 
    if (window.location.hash !== hash) { 
     window.location.hash = hash; 
    } 
    }); 

    window.addEventListener('hashchange',() => { 
    const hash = window.location.hash; 
    const savedHash = hashFromState(store.getState()); 
    if (savedHash !== hash) { 
     store.dispatch({ 
     type: CHANGE_HASH, 
     hash 
     }); 
    } 
    }, false); 

    store.dispatch({ 
    type: CHANGE_HASH, 
    hash: window.location.hash 
    }); 

    function liftReducer(reducer) { 
    return (state, action) => { 
     if (action.type !== CHANGE_HASH) { 
     return reducer(state, action); 
     } else { 
     return stateFromStateAndHash(state, action.hash); 
     } 
    } 
    } 

    return { 
    ...store, 
    replaceReducer: (reducer) => { 
     return store.replaceReducer(liftReducer(reducer)) 
    } 
    } 
}; 

使用:

export const store = createStore(
    reducer, 
    initialState, 
    hashEnhancer(hashFromState, stateFromStateAndHash) 
); 

hashFromStateタイプハッシュ=>状態の関数であり、そしてstateFromStateAndHashは(状態、ハッシュ)=>状態関数です。

ルータが単純化され、反応ルータや反応ルータが完全に理解できない場合があります。

関連する問題