React HOC TypeScript通过Redux连接消除任何类型



总体思想是一个提供翻译能力的包装器组件。

顺便说一句,完整的例子在这里https://codesandbox.io/s/quizzical-hellman-v84ed或GitHubhttps://github.com/hitrov/translation-wrapper

这是HOC签名

export const wrapper = <P extends object>(Component: React.ComponentType<P>) =>
(props: P & WithReplacementProps & IProps) => {...}

自变量组件必须通过提供内容

interface WithReplacementProps {
translatableProps: {
getHeader(): string;
getContent(): string;
}
}

Redux应注入

interface IProps {
language: string;
setLanguage(language: string): SetLanguage;
}

就是这样做的

type StateProps = Pick<IProps, | 'language'>;
type DispatchProps = Pick<IProps, | 'setLanguage'>;
type OwnProps = Omit<
IProps,
keyof StateProps | keyof DispatchProps
>;
const connector = connect<StateProps, DispatchProps, OwnProps, RootState>((state: RootState) => ({
language: state.language,
}), {
setLanguage,
});

问题是,当我试图用允许安全检查类型的东西替换<any>时,我总是会遇到TypeScript错误。

export function withReplacement<T>(Component: React.ComponentType<T>) {
return connector(wrapper<any>(Component));
}

最后是我如何使用包装组件

const ContentWithReplacement = withReplacement(Content);
...
<ContentWithReplacement
key={header}
header={header}
content={content}
translatableProps={{
getContent: () => content,
getHeader: () => header,
}}
/>

内容组件是直通

export function Content(props: ContentProps) {
const { translatedProps } = props;
return (
<>
<h1>{translatedProps && translatedProps.header}</h1>
<p>{translatedProps && translatedProps.content}</p>
</>
);
}

解决了问题。这对我帮助很大https://github.com/piotrwitek/react-redux-typescript-guide#--嵌套hoc-封装组件-投影-属性-连接到redux-

这就是我连接的HOC目前的样子

import React, { useReducer, useState } from "react";
import { reducer } from "../reducers";
import { Select } from "../Select";
import { connect } from 'react-redux';
import { RootState } from "../reducers/redux";
import { setLanguage, SetLanguage, } from '../reducers/language';
import { Diff } from 'utility-types';
interface InjectedProps {
language: string;
setLanguage(language: string): SetLanguage;
}
interface WithReplacementProps {
translatableProps: {
getHeader(): string;
getContent(): string;
}
}
export const withReplacement = <BaseProps extends {}>
(Component: React.ComponentType<BaseProps>) => {
const mapStateToProps = (state: RootState) => ({
language: state.language,
});
const dispatchProps = {
setLanguage: (language: string) => setLanguage(language),
};
type PropsFromRedux = ReturnType<typeof mapStateToProps> &
typeof dispatchProps & {
// here you can extend ConnectedHoc with new props
// overrideCount?: number;
};
const Hoc = (props: PropsFromRedux & WithReplacementProps) => {
const { translatableProps, language, setLanguage, ...rest } = props;
const [ showOriginal, setShowOriginal ] = useState(true);
const { getHeader, getContent } = translatableProps;
let header = getHeader();
let content = getContent();
const [ state, dispatch ] = useReducer(reducer, {...);
return (
<>
<Component
{...rest as BaseProps}
translatedProps={{
header,
content,
}}
/>
<Select
language={language}
onChange={e => {
setLanguage(e.target.value);
}}
/>
</>
);
};
return connect<ReturnType<typeof mapStateToProps>,
typeof dispatchProps, // use "undefined" if NOT using dispatchProps
Diff<BaseProps, InjectedProps>,
RootState>(
mapStateToProps,
dispatchProps
)(Hoc);
};

最新更新