2016-04-13 12 views
6

tepki: Bir input[type="search"] olduğunu bir controlled component. Daha sonra, bu bileşenin değiştirilmesinin 1 saniyesinden sonra, o aramayı yürütmek için bir HTTP çağrısı göndermek ve sonuçları başka bir bileşende göstermek istiyorum.Doğru yolu redux devlet dayalı HTTP çağrıları azaltmasını ve ben gerekenler

bunu yaptık Nasıl: Ben dispatch(setSearch(str)); her aradığında Ben dispatch(displaySearch(false)); için arama yapmak ve bileşende işin bu tür yapıyor yanlış olduğunu o zaman _.throttle Bana hissediyor dispatch(displaySearch(true));

çağrısı ama redux’da redüktörde bunu yapmanın bir yolunu düşünemiyorum.

+0

(tüm API çağrıları için gibi) ya da yalnızca bu bileşen için tüm uygulama için someting küresel ister misin? – KeitIG

+0

Uygulamanın bu bölümündeki diğer bileşenlerde kullanıldığını görebiliyordum. – Dave

+0

http://stackoverflow.com/questions/23123138/perform-debounce-in-react-js/28046731#28046731 –

cevap

4

Bunu çözmek için farklı seçenekleriniz var.

1. Sıçrama bir bileşen seviyesinde

Bu adresinden eylem basit bir yaklaşımdır. Giriş bir değişikliği tetiklediğinde, numaralı çağrıyı, sunucu çağrısını geciktiren setSearch bir geri döndürülen sürümünü çağırır.

import * as React from "react" 
import {connect} from "react-redux" 
import {setSearch} from "./actions" 

export default connect(
    null, 
    function mapDispatchToProps(dispatch) { 
    const setSearch_ = _.debounce(q => dispatch(setSearch(q)), 1000) 
    return() => ({setSearch: setSearch_}) 
    } 
)(
    function SearchForm(props) { 
    const {setSearch} = props 
    return (
     <input type="search" onChange={setSearch} /> 
    ) 
    } 
) 

2. redux-saga

Bu yaklaşım kullanarak Sıçrama fazla klişe gerektirir fakat iş akışı üzerinde çok daha fazla kontrol sağlar. efsanesi'u kullanarak, SET_SEARCH eylemini kesiyoruz, geri döndürüyoruz, API'yi arayınız ve sonuçları içeren yeni bir eylem gönderiniz.

import {call, cancel, fork, put, take} from "redux-saga/effects" 
import {setSearchResults} from "./actions" 
import {api} from "./services" 
import {delay} from "./utils" 

export default function* searchSaga() { 
    yield [ 
    // Start a watcher to handle search workflow 
    fork(watchSearch) 
    ] 
} 

function* watchSearch() { 
    let task 

    // Start a worker listening for `SET_SEARCH` actions. 
    while (true) { 
    // Read the query from the action 
    const {q} = yield take("SET_SEARCH") 

    // If there is any pending search task then cancel it 
    if (task) { 
     yield cancel(task) 
    } 

    // Create a worker to proceed search 
    task = yield fork(handleSearch, q) 
    } 
} 

function* handleSearch(q) { 
    // Debounce by 1s. This will lock the process for one second before 
    // performing its logic. Since the process is blocked, it can be cancelled 
    // by `watchSearch` if there are any other actions. 
    yield call(delay, 1000) 

    // This is basically `api.doSearch(q)`. The call should return a `Promise` 
    // that will resolve the server response. 
    const results = yield call(api.doSearch, q) 

    // Dispatch an action to notify the UI 
    yield put(setSearchResults(results)) 
} 
+1

Hatalı bir fikir: "mapDispatchToProps" üzerinde geri dönen işlevi oluşturmak, her seferinde geri döndürülen işlevin yeniden oluşturulacağı anlamına gelir değişiklikler, yani aslında geri alınmayacak demektir. Redux-saga için ayrıca bir belge var: http://yelouafi.github.io/redux-saga/docs/recipes/index.html –

+0

@SebastienLorber 'mapDispatchToProps' hakkında haklıydınız. Cevabımı güncelledim, artık böyle değil, teşekkürler! Ve evet, örnek kodum redux destanı tariflerinden ödünç alındı. – Florent

1

Ön delay ve takeLatest:

import { all, takeLatest, call } from 'redux-saga/effects'; 
import { delay } from 'redux-saga'; 


function* onSearch(action) { 
    yield call(delay, 1000); // blocks until a new action is 
          // triggered (takeLatest) or until 
          // the delay of 1s is over 

    const results = yield call(myFunction); 
} 

function* searchSagas() { 
    yield all([ 
    // ... 
    takeLatest(ON_SEARCH, onSearch), 
    ]); 
} 

export default [searchSagas];