在 .NET Core 2.0 reactredux 模板项目中使用 react redux 和 typescript 将组件与 OwnProps 连接起来
Posted
技术标签:
【中文标题】在 .NET Core 2.0 reactredux 模板项目中使用 react redux 和 typescript 将组件与 OwnProps 连接起来【英文标题】:Connecting a component with OwnProps using react redux and typescript in the .NET Core 2.0 reactredux template project 【发布时间】:2018-05-18 10:08:38 【问题描述】:源代码可以在这里找到:https://github.com/cvanem/ASPNETCoreReact16Redux
编辑:我能够使用以下代码使其 99% 正常工作。一切都在编译时运行,但在父组件中使用时,它会警告说属性计数丢失。实际执行时,一切都按预期工作。此计数属性位于 CounterStore 中,并在按下按钮时正确递增。一切正常,但我不知道如何摆脱打字稿警告。我在某处做错类型定义了吗?原始模板将 typeof Counter 添加到连接语句的末尾,如下所示:
export default connect(mapStateToProps, mapStateToDispatch )(Counter) as typeof Counter;
当我用我的代码尝试上述操作时,它给出了以下错误:
ERROR in [at-loader] ./ClientApp/components/Counter.tsx:39:16
TS2352: Type 'ComponentClass<Pick<CounterState & ComponentProps & increment: () => IncrementCountAction; decr...' cannot be converted to type 'typeof Counter'.
ERROR in [at-loader] ./ClientApp/components/Counter.tsx:39:16
TS2352: Type 'ComponentClass<Pick<CounterState & ComponentProps & increment: () => IncrementCountAction; decr...' cannot be converted to type 'typeof Counter'.
Type 'Component<Pick<CounterState & ComponentProps & increment: () => IncrementCountAction; decrement...' is not comparable to type 'Counter'.
Types of property 'setState' are incompatible.
Type ' <K extends never>(f: (prevState: Readonly<ComponentState>, props: Pick<CounterState & Component...' is not comparable to type ' <K extends never>(f: (prevState: Readonly<>, props: CounterState & ComponentProps & increme...'.
Types of parameters 'f' and 'f' are incompatible.
Types of parameters 'props' and 'props' are incompatible.
Type 'Pick<CounterState & ComponentProps & increment: () => IncrementCountAction; decrement: () => De...' is not comparable to type 'CounterState & ComponentProps & increment: () => IncrementCountAction; decrement: () => Decreme...'.
Type 'Pick<CounterState & ComponentProps & increment: () => IncrementCountAction; decrement: () => De...' is not comparable to type 'CounterState'.
Property 'count' is missing in type 'Pick<CounterState & ComponentProps & increment: () => IncrementCountAction; decrement: () => De...'.
ERROR in [at-loader] ./ClientApp/components/Home.tsx:16:13
TS2322: Type ' test: "hello"; children: never[]; ' is not assignable to type 'IntrinsicAttributes & IntrinsicClassAttributes<Counter> & Readonly< children?: ReactNode; > & R...'.
Type ' test: "hello"; children: never[]; ' is not assignable to type 'Readonly<CounterState & ComponentProps & increment: () => IncrementCountAction; decrement: () =...'.
Property 'count' is missing in type ' test: "hello"; children: never[]; '.
这是我所拥有的,它可以编译并工作,但仍然给出设计时警告:
export default connect(mapStateToProps, mapStateToDispatch )(Counter);
有什么想法吗?这是包含所有内容的完整组件代码,但当 Counter 组件被父组件(即)使用时,仍会在设计时发出打字稿警告:
import * as React from 'react';
import Link, RouteComponentProps from 'react-router-dom';
import connect from 'react-redux';
import ApplicationState from '../store';
import * as CounterStore from '../store/Counter';
type ComponentStateProps = CounterStore.CounterState & ComponentProps; //type definition for component props merged with state props (for typings on the connect function)
type CounterProps = ComponentStateProps & typeof CounterStore.actionCreators;
//type definition for the component class
interface ComponentProps
test: string;
class Counter extends React.Component<CounterProps, >
public render()
return <div>
<h1>Counter</h1>
<p>This is a simple example of a React component.</p>
<p>Current count: <strong> this.props.count </strong></p>
<button onClick=() => this.props.increment()
>Increment</button>
<p>Component Prop = this.props.test</p>
</div>;
const mapStateToProps = (state: ApplicationState, ownProp: ComponentProps):
ComponentStateProps =>
return (
...state.counter,
test: ownProp.test
);
;
const mapStateToDispatch = CounterStore.actionCreators;
export default connect(mapStateToProps, mapStateToDispatch )(Counter);
原帖:
我从 Visual Studio 2017 模板创建了一个新的 react redux 项目,方法是在命令提示符下运行:
dotnet new reactredux
我正在尝试将一个组件连接到 redux 商店。组件有它自己的属性,ComponentProps。当我尝试使用它自己的属性将它连接到商店时,我收到以下错误:
./ClientApp/components/Counter.tsx:34:5
TS2345: Argument of type '(state: ApplicationState) => CounterState' is not assignable to parameter of type 'MapStateToPropsParam<, ComponentProps,>'.
Type '(state: ApplicationState) => CounterState' is not assignable to type 'MapStateToProps<, ComponentProps, >'.
Types of parameters 'state' and 'state' are incompatible.
Type '' is not assignable to type 'ApplicationState'.
Property 'counter' is missing in type ''.
我添加了 ComponentProps 接口,将其包含在 CounterProps 中,并将其添加到底部的连接调用中。这是组件代码:
import * as React from 'react';
import Link, RouteComponentProps from 'react-router-dom';
import connect from 'react-redux';
import ApplicationState from '../store';
import * as CounterStore from '../store/Counter';
import * as WeatherForecasts from '../store/WeatherForecasts';
interface ComponentProps
test: string;
type CounterProps =
CounterStore.CounterState
& typeof CounterStore.actionCreators
& RouteComponentProps<>
& ComponentProps;
class Counter extends React.Component<CounterProps, >
public render()
return <div>
<h1>Counter</h1>
<p>This is a simple example of a React component.</p>
<p>Current count: <strong> this.props.count </strong></p>
<button onClick= () => this.props.increment()
>Increment</button>
</div>;
// Wire up the React component to the Redux store
export default connect<, , ComponentProps>(
(state: ApplicationState) => state.counter, // Selects which state properties are merged into the component's props
CounterStore.actionCreators, // Selects which action creators are merged into the component's props
)(Counter) as typeof Counter;
有人可以告诉我使用 connect 将具有自己属性的组件连接到商店的正确方法吗?我尝试的一切似乎都会产生错误。 @types/react-redux 文件有一个关于传递第三个参数的注释,并说用户必须扩展 ownProps 接口,但我不确定如何做到这一点。这是 index.d.ts 文件中@types/react-redux 的部分:
/**
* Connects a React component to a Redux store.
*
* - Without arguments, just wraps the component, without changing the behavior / props
*
* - If 2 params are passed (3rd param, mergeProps, is skipped), default behavior
* is to override ownProps (as stated in the docs), so what remains is everything that's
* not a state or dispatch prop
*
* - When 3rd param is passed, we don't know if ownProps propagate and whether they
* should be valid component props, because it depends on mergeProps implementation.
* As such, it is the user's responsibility to extend ownProps interface from state or
* dispatch props or both when applicable
*
* @param mapStateToProps
* @param mapDispatchToProps
* @param mergeProps
* @param options
*/
export interface Connect
(): InferableComponentEnhancer<DispatchProp<any>>;
<TStateProps = , no_dispatch = , TOwnProps = , State = >(
mapStateToProps: MapStateToPropsParam<TStateProps, TOwnProps,
State>): InferableComponentEnhancerWithProps<TStateProps &
DispatchProp<any>, TOwnProps>;
<no_state = , TDispatchProps = , TOwnProps = >(
mapStateToProps: null | undefined,
mapDispatchToProps: MapDispatchToPropsParam<TDispatchProps,
TOwnProps>
): InferableComponentEnhancerWithProps<TDispatchProps,
TOwnProps>;
<TStateProps = , TDispatchProps = , TOwnProps = , State = >(
mapStateToProps: MapStateToPropsParam<TStateProps, TOwnProps,
State>,: MapDispatchToPropsParam<TDispatchProps, TOwnProps>
): InferableComponentEnhancerWithProps<TStateProps &
TDispatchProps, TOwnProps>;
<TStateProps = , no_dispatch = , TOwnProps = , TMergedProps =
, State = >(: MapStateToPropsParam<TStateProps, TOwnProps,
State>,: null | undefined,: MergeProps<TStateProps, undefined,
TOwnProps, >,<TMergedProps, TOwnProps>;
<no_state = , TDispatchProps = , TOwnProps = , TMergedProps =
>(: null | undefined,: MapDispatchToPropsParam<TDispatchProps,
TOwnProps>,: MergeProps<undefined, TDispatchProps, TOwnProps,
TMergedProps>,<TMergedProps, TOwnProps>;
<no_state = , no_dispatch = , TOwnProps = , TMergedProps = >
(: null | undefined,: null | undefined,: MergeProps<undefined,
undefined, TOwnProps, TMergedProps>,<TMergedProps, TOwnProps>;
<TStateProps = , TDispatchProps = , TOwnProps = , TMergedProps
= , State = >(: MapStateToPropsParam<TStateProps,
TOwnProps, State>,: MapDispatchToPropsParam<TDispatchProps,
TOwnProps>,: MergeProps<TStateProps, TDispatchProps, TOwnProps,
TMergedProps>,<TMergedProps, TOwnProps>;
<TStateProps = , no_dispatch = , TOwnProps = , State = >(
mapStateToProps: MapStateToPropsParam<TStateProps, TOwnProps,
State>,: null | undefined,: null | undefined,: Options<State,
TStateProps, TOwnProps>):
InferableComponentEnhancerWithProps<DispatchProp<any> &
TStateProps, TOwnProps>;
<TStateProps = , TDispatchProps = , TOwnProps = >(
mapStateToProps: null | undefined,:
MapDispatchToPropsParam<TDispatchProps, TOwnProps>,
mergeProps: null | undefined,: Options<, TStateProps,
TOwnProps><TDispatchProps, TOwnProps>;
<TStateProps = , TDispatchProps = , TOwnProps = , State = >(
mapStateToProps: MapStateToPropsParam<TStateProps, TOwnProps,
State>,: MapDispatchToPropsParam<TDispatchProps, TOwnProps>,
mergeProps: null | undefined,: Options<State, TStateProps,
TOwnProps>): InferableComponentEnhancerWithProps<TStateProps &
TDispatchProps, TOwnProps>;
<TStateProps = , TDispatchProps = , TOwnProps = , TMergedProps
= , State = >(mapStateToProps:
MapStateToPropsParam<TStateProps, TOwnProps,
State>,mapDispatchToProps:
MapDispatchToPropsParam<TDispatchProps, TOwnProps>,
mergeProps: MergeProps<TStateProps, TDispatchProps, TOwnProps,
TMergedProps>,
options: Options<State, TStateProps, TOwnProps, TMergedProps>
): InferableComponentEnhancerWithProps<TMergedProps,
TOwnProps>;
【问题讨论】:
嘿,你解决这个问题了吗?我有同样的问题。一切都很好,直到我尝试在另一个组件中使用组件。就像我需要传递 @connect 应该在内部提供的所有道具。除非我有什么问题。 【参考方案1】:使用一些Domain
:
export type DomainState = Readonly<
isLoaded: boolean;
isLoadedError: boolean;
model: IDomainModel;
error: any;
>;
export interface IDomainStore
domain: DomainState;
interface IDomainPageCompProps extends
RouteComponentProps<IDomainRoutingParams>
isLoadedError: boolean;
isLoaded: boolean;
resources: any;
import connect from 'react-redux';
import IDomainPageCompProps, DomainPage from '...';
import IDomainStore from '../store';
import RouteComponentProps, withRouter from 'react-router';
import IDomainRoutingParams from '../types/routing-params';
interface IOwnProps extends RouteComponentProps<IDomainRoutingParams>
resources;
const connected = connect<IDomainPageCompProps, , IOwnProps, IDomainStore>(
(store: IDomainStore, ownProps: IOwnProps) =>
return
...ownProps,
isLoaded: store.domain.isLoaded,
isLoadedError: store.domain.isLoadedError
;
,
(/* dispatch */) =>
return ;
)(DomainPage);
export const DomainPageContainer = withRouter(connected);
// .jsx
<Provider store=store>
<DomainPageContainer resources=... />
</Provider>
【讨论】:
以上是关于在 .NET Core 2.0 reactredux 模板项目中使用 react redux 和 typescript 将组件与 OwnProps 连接起来的主要内容,如果未能解决你的问题,请参考以下文章
Azure Functions .NET Core 中的 EF Core 2.0 连接字符串
如何在新创建的 .NET Core 2.0 Web 应用程序中定位 .NET Standard 2.0?