Mam problem z ustaleniem, jak poprawnie wpisać Redux containers.TypScript walczy z kontenerami Redux
Rozważmy prosty prezentacyjnego składnik, który może wyglądać następująco:
interface MyProps {
name: string;
selected: boolean;
onSelect: (name: string) => void;
}
class MyComponent extends React.Component<MyProps, {}> { }
Z perspektywy tego składnika są wymagane wszystkie rekwizyty.
Teraz chcę napisać pojemnik, który ściąga wszystkie te rekwizyty z państwa:
function mapStateToProps(state: MyState) {
return {
name: state.my.name,
selected: state.my.selected
};
}
function mapDispatchToProps(dispatch: IDispatch) {
return {
onSelect(name: string) {
dispatch(mySelectAction(name));
}
};
}
const MyContainer = connect(
mapStateToProps,
mapDispatchToProps
)(MyComponent);
To działa, ale nie jest to duży problem, wpisując: funkcje mapowania (mapStateToProps
i mapDispatchToProps
) posiadają żadnej ochrony, że dostarczają odpowiednich danych do spełnienia MyProps
. Jest to skłonne do błędów, literówek i złego refaktoryzacji.
mogłem zrobić funkcje mapowania typu MyProps
powrotu:
function mapStateToProps(state: MyState): MyProps { }
function mapDispatchToProps(dispatch: IDispatch): MyProps { }
Jednak to nie działa, chyba że zrobię wszystko MyProp
rekwizyty opcjonalne, tak, że każda funkcja mapowania może zwrócić tylko część dbają o. Nie chcę, aby rekwizyty były opcjonalne, ponieważ nie są opcjonalne w stosunku do komponentu prezentacji.
Inną opcją jest podzielona rekwizyty dla każdej funkcji mapy i połączyć je do podpór składowych:
// MyComponent
interface MyStateProps {
name: string;
selected: boolean;
}
interface MyDispatchProps {
onSelect: (name: string) => void;
}
type MyProps = MyStateProps & MyDispatchProps;
class MyComponent extends React.Component<MyProps, {}> { }
// MyContainer
function mapStateToProps(state: MyState): MyStateProps { }
function mapDispatchToProps(dispatch: IDispatch): MyDispatchProps { }
Ok, że coraz mnie bliżej do tego, co chcę, ale jego rodzaj głośny i jego tworzenia piszę mój prezentacyjny komponentowy interfejs propowy wokół kształtu kontenera, którego nie lubię.
A teraz pojawia się drugi problem. Co zrobić, jeśli chcę umieścić pojemnik wewnątrz innego składnika:
<MyContainer />
Daje skompilować błędy name
, selected
i onSelect
są brakujące ... ale to jest celowe, ponieważ pojemnik jest podłączenie do Redux i dostarczanie tych. Więc to zmusza mnie do tego, by wszystkie komponenty były opcjonalne, ale nie podoba mi się to, ponieważ nie są one opcjonalne.
Robi się gorzej, gdy MyContainer
ma jedne z własnych rekwizytów, że chce być przekazywane w:
<MyContainer section="somethng" />
Teraz co próbuję zrobić, to mieć section
wymaganym rekwizytem MyContainer
ale nie rekwizyt z MyComponent
i name
, selected
i onSelect
są wymagane podpory MyComponent
, ale opcjonalne lub nie rekwizyty w ogóle z MyContainer
. Nie jestem w stanie wyrazić tego.
Wszelkie wskazówki na ten temat będą mile widziane!
Dzięki, że to pomaga. Domyślam się, że bez TypeScript wszystko jest opcjonalne. Po prostu podoba mi się to, że rekwizyty części mogą ci powiedzieć, jakie rzeczy są oczekiwane, a jakie opcjonalne. – Aaron
Pytanie: ponieważ to rozwiązanie w zasadzie oznacza, że definiujesz każdą propę dwukrotnie (raz w 'MyProps' i raz w odpowiednim' MyStateProps' lub 'MyDispatchProps'), co się stanie, jeśli zmienisz nazwę lub zmienisz rekwizyt w' MyProps', na przykład "nazwa" do "id" lub "selected: boolean" na "selected: SelectionEnum"? Czy kontroler typu zdaje sobie sprawę, że 'MyOwnProps, MyDispatchProps, MyStateProps' nie spełnia już' MyProps'? – Aaron
Nieco. Bawiłem się z tym od czasu napisania odpowiedzi. Rekwizyty State i Dispatch muszą się zgadzać, ale OwnProps nie muszą się zgadzać. Myślę, że może dlatego, że można używać selfProps tylko w mapStateToProps i mapDispatchToProps i nie używać ich w MyComponent? –