2017-06-23 41 views
5

Mam pewne niedogodności związane z działaniem maszynopisu i działań redux-thunk.Skrypt z programem Redux, jak używać połączenia bez ponownego deklarowania definicji działania?

Zasadniczo moje komponenty intensywnie wykorzystują łączenie reaguj-redux, aby powiązać twórców akcji, problem polega na tym, że kiedy tworzę interfejs dla tych działań redux w ramach komponentu, muszę ponownie zadeklarować definicję funkcji, ponieważ ginie ona w wywołaniu połączenia.

Oto przykładowy kod:

Action Twórca

import api from './api'; 
import { Dispatch } from 'redux'; 
import { IReduxAction } from 'model'; 

export const FETCH_ENTITY = 'location/FETCH_ENTITY'; 
export function fetchEntity(id: string) { 
    return (dispatch: Dispatch<IReduxAction>) => { 
    dispatch({type: `${FETCH_ENTITY}_REQUEST`, payload: {id}}); 

    return api.fetchEntity(id) 
       .then((res) => { 

       dispatch({ type: `${FETCH_ENTITY}_DONE`, payload: res }); 
       return res; 
       }) 
       .catch((err) => { 
       dispatch({type: `${FETCH_ENTITY}_FAIL`, payload: err, error: true}); 
       throw err; 
       }); 
    }; 
} 

Komponent

import * as React from 'react'; 
import { bindActionCreators } from 'redux'; 
import { connect } from 'react-redux'; 

import { 
    fetchEntity, 
} from 'actions'; 

interface IStateProps { 
    startingEntities: any[]; 
} 

interface IDispatchProps { 
    fetchEntity: (id: string) => Promise<any>; // <- this is what I'm trying to get rid of, basically whenever I change the action creator I have to change this definition everytime 
} 

class Dashboard extends React.Component<IStateProps & IDispatchProps, void> { 

    public render() { 

    return (<div>...RENDER SOMETHING...</div>); 
    } 

} 

const mapStateToProps = (state: any, ownProps: any) => { 
    const startingEntities = foo(); // not important 

    return { 
    startingEntities, 
    }; 
}; 

const mapDispatchToProps = (dispatch: any) => { 
    return bindActionCreators({ 
    fetchEntity 
    }, dispatch); 
}; 

export default connect<IStateProps, IDispatchProps, void>(mapStateToProps, mapDispatchToProps)(Dashboard); 

Czy mimo zadeklarować ten binded twórca działania bez konieczności ponownego zadeklarować go za każdym razem na każdy plik?

Odpowiedz

6

Nie trzeba ponownie zdefiniować rodzaj funkcji. Można użyć typeof:

interface IDispatchProps { 
    fetchEntity: typeof fetchEntity 
} 
0

Nie jestem pewien, czy rozumiem wzór, którego szukasz, ale twórca działania jest po prostu prostym obiektem z właściwością 'typ' wymaganą dla reduktora, gdy go używa.

Dlatego zakładam, że najlepszym sposobem na to jest uzyskanie dedykowanego pliku z działaniami, które wyeksportujesz, a następnie zaimportujesz je. Twoja logika na temat wyboru akcji do dispatc będzie w twoim zachowaniu komponentowym, co wydaje mi się lepsze.

Mam nadzieję, że to pomoże i rozwiązać swój problem :)

+0

Dzięki za komentarz, ale to nie jest mój problem, jak można zobaczyć moje działania są już w oddzielnym pliku (import { fetchEntity, } z „działań”;) I” Próbuję radzić sobie z definicjami typów dla moich działań, a konkretnie, ponownie deklarować definicję typu za każdym razem, gdy używam 'connect' w komponencie. – ospfranco

+0

Ok, moje rozumienie maszynopisu przeszkadza mi w udzielaniu większej pomocy :(przepraszam –

1

Nie jestem zbyt obeznany z maszynopisu (głównie właśnie zrobić index.d.ts plików interfejsów bibliotecznych), ale powinieneś być w stanie dostać się do systemu typu zrobić praca dla ciebie przez poprawne wpisanie fetchEntity i eksportowanie jej do użycia w IDispatchProps. Coś jak

//... 

import { ThunkAction } from 'redux-thunk' 

//... 

export interface FetchEntity { 
    (id: string): ThunkAction<Promise<any>, IReduxAction, any>; 
} 

//... 

export const fetchEntity: FetchEntity = (id: string) => { 
    return (dispatch: Dispatch<IReduxAction>) => { 
    //... 
    }; 
} 

A potem można go importować i wykorzystywać tę samą definicję

//... 

import { 
    fetchEntity, 
    FetchEntity 
} from 'actions'; 

//... 

interface IDispatchProps { 
    fetchEntity: FetchEntity 
} 

//... 
+0

Wydawało mi się, że działa dobrze, ale kiedy próbowałem skompilować kod zdałem sobie sprawę, że typ nie jest obietnicą, w moim kodzie używam a. Następnie po wywołaniu jest zakończony, aby wykonać jakąś inną akcję interfejsu użytkownika, może używam anty wzorca? – ospfranco

+0

@spfranco, myślę, że Ninten ma lepsze rozwiązanie w każdym razie –

+0

Odpowiedź Ninten również cierpi na ten sam problem, definicja thunk nie jest obietnicą, jako taka Nie mogę wywołać metody .then() na tym typie – ospfranco

Powiązane problemy