可在此处找到源代码:https://github.com/cvanem/ASPNETCoreReact16Redux
编辑:我能够使用以下代码获得99%。一切都在编译时运行,但是当在父组件中使用时,它会发出一个警告,指出缺少属性计数。实际执行时,一切都按预期工作。此计数属性位于CounterStore中,并在按下按钮时正确递增。一切正常,但我不知道如何摆脱打字稿警告。我在某个地方做错了吗?原始模板将typeof Counter添加到connect语句的末尾,如下所示: 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组件被父组件使用时,仍然会给出typescript警告:(例如):
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中并将其添加到底部的connect调用中。这是组件代码:
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接口的注释,但我不确定如何做到这一点。以下是@ types / react-redux的index.d.ts文件中的部分:
/**
* 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>;
}
答案 0 :(得分:0)
使用一些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>