属性 当使用 recompose 定义时,React 组件上不存在
Property does not exist on React component when defined with recompose
我正在使用 create-react-app 和 typescript 脚本作为基础,试图获得一个使用 recompose 的简单示例。
问题是我无法将 属性 直接发送到组件。
我创建了一个简单的用户组件 ./components/User.tsx
:
import * as React from 'react';
import { compose, withState, withHandlers } from 'recompose';
export interface WithStateProps {
counter: number
setCounter: (x: (c: number) => number) => void;
}
export interface WithHandlerProps {
increment: () => void
decrement: () => void
}
interface ComponentProps {
name: string
}
export type ComposedProps = WithStateProps & WithHandlerProps
export type UserProps = ComposedProps & ComponentProps
export const enhance = compose<UserProps, {}>(
withState<WithStateProps, number, 'counter', 'setCounter'>('counter', 'setCounter', 1),
withHandlers<UserProps, UserProps>({
increment: ({ setCounter }) => () => setCounter( n => n + 1 ),
decrement: ({ setCounter }) => () => setCounter( n => n - 1 )
})
)
const User: React.StatelessComponent<UserProps> = ({counter, increment, decrement, name}: UserProps) => (
<div className='User'>
{name} : counter : {counter}
<div>
<button onClick={increment}> add </button>
<button onClick={decrement}> remove </button>
</div>
</div>
)
export default enhance(User)
我在 index.tsx
:
中使用它
import * as React from 'react';
import * as ReactDOM from 'react-dom';
import { Provider } from 'react-redux';
import registerServiceWorker from './registerServiceWorker';
import './index.css';
import User from './components/User'
import { createStore } from 'redux';
import { enthusiasm } from './reducers/index';
import { StoreState } from './types/index';
const store = createStore<StoreState>(enthusiasm, {
enthusiasmLevel: 1,
languageName: 'TypeScript',
});
ReactDOM.render(
<Provider store={store}>
<div>
<User />
</div>
</Provider>,
document.getElementById('root') as HTMLElement
);
registerServiceWorker();
上面的工作正常,但如果我改用下面的:
<User name='andrew hopkins' />
我收到以下错误消息:
./src/index.tsx
(22,13): error TS2339: Property 'name' does not exist on type 'IntrinsicAttributes & IntrinsicClassAttributes<Component<{}, ComponentState>> & Readonly<{ childr...'.
我的package.json file
:
{
"name": "ts-rxjs-recompose",
"version": "0.1.0",
"private": true,
"dependencies": {
"react": "^16.0.0",
"react-dom": "^16.0.0",
"react-redux": "^5.0.6",
"react-scripts-ts": "2.7.0",
"recompose": "^0.25.1",
"redux": "^3.7.2"
},
"scripts": {
"start": "react-scripts-ts start",
"build": "react-scripts-ts build",
"test": "react-scripts-ts test --env=jsdom",
"eject": "react-scripts-ts eject"
},
"devDependencies": {
"@types/enzyme": "^2.8.9",
"@types/jest": "^21.1.1",
"@types/node": "^8.0.31",
"@types/react": "^16.0.7",
"@types/react-dom": "^15.5.5",
"@types/react-redux": "^5.0.9",
"@types/recompose": "^0.24.2",
"enzyme": "^3.0.0",
"react-addons-test-utils": "^15.6.2"
}
}
解决方案是对 TOutter
类型使用 ComponentProps
进行撰写:
export const enhance = compose<UserProps, ComponentProps>(
这是因为,查看 compose
的类型定义
export function compose<TInner, TOutter>(
...functions: Function[]
): ComponentEnhancer<TInner, TOutter>;
我作为 TInner
通过 UserProps
,但是 TOutter
增强组件的空对象导致了错误。
编辑:
为了扩展答案,TOutter
是外部组件的类型,在本例中是将接收名称道具的类型,即 index.tsx
中使用的 <User />
组件。 TInner
期望内部组件的类型将接收使用重组创建的所有道具,在本例中为 ./components/User.tsx
中的 User
组件。
我正在使用 create-react-app 和 typescript 脚本作为基础,试图获得一个使用 recompose 的简单示例。
问题是我无法将 属性 直接发送到组件。
我创建了一个简单的用户组件 ./components/User.tsx
:
import * as React from 'react';
import { compose, withState, withHandlers } from 'recompose';
export interface WithStateProps {
counter: number
setCounter: (x: (c: number) => number) => void;
}
export interface WithHandlerProps {
increment: () => void
decrement: () => void
}
interface ComponentProps {
name: string
}
export type ComposedProps = WithStateProps & WithHandlerProps
export type UserProps = ComposedProps & ComponentProps
export const enhance = compose<UserProps, {}>(
withState<WithStateProps, number, 'counter', 'setCounter'>('counter', 'setCounter', 1),
withHandlers<UserProps, UserProps>({
increment: ({ setCounter }) => () => setCounter( n => n + 1 ),
decrement: ({ setCounter }) => () => setCounter( n => n - 1 )
})
)
const User: React.StatelessComponent<UserProps> = ({counter, increment, decrement, name}: UserProps) => (
<div className='User'>
{name} : counter : {counter}
<div>
<button onClick={increment}> add </button>
<button onClick={decrement}> remove </button>
</div>
</div>
)
export default enhance(User)
我在 index.tsx
:
import * as React from 'react';
import * as ReactDOM from 'react-dom';
import { Provider } from 'react-redux';
import registerServiceWorker from './registerServiceWorker';
import './index.css';
import User from './components/User'
import { createStore } from 'redux';
import { enthusiasm } from './reducers/index';
import { StoreState } from './types/index';
const store = createStore<StoreState>(enthusiasm, {
enthusiasmLevel: 1,
languageName: 'TypeScript',
});
ReactDOM.render(
<Provider store={store}>
<div>
<User />
</div>
</Provider>,
document.getElementById('root') as HTMLElement
);
registerServiceWorker();
上面的工作正常,但如果我改用下面的:
<User name='andrew hopkins' />
我收到以下错误消息:
./src/index.tsx
(22,13): error TS2339: Property 'name' does not exist on type 'IntrinsicAttributes & IntrinsicClassAttributes<Component<{}, ComponentState>> & Readonly<{ childr...'.
我的package.json file
:
{
"name": "ts-rxjs-recompose",
"version": "0.1.0",
"private": true,
"dependencies": {
"react": "^16.0.0",
"react-dom": "^16.0.0",
"react-redux": "^5.0.6",
"react-scripts-ts": "2.7.0",
"recompose": "^0.25.1",
"redux": "^3.7.2"
},
"scripts": {
"start": "react-scripts-ts start",
"build": "react-scripts-ts build",
"test": "react-scripts-ts test --env=jsdom",
"eject": "react-scripts-ts eject"
},
"devDependencies": {
"@types/enzyme": "^2.8.9",
"@types/jest": "^21.1.1",
"@types/node": "^8.0.31",
"@types/react": "^16.0.7",
"@types/react-dom": "^15.5.5",
"@types/react-redux": "^5.0.9",
"@types/recompose": "^0.24.2",
"enzyme": "^3.0.0",
"react-addons-test-utils": "^15.6.2"
}
}
解决方案是对 TOutter
类型使用 ComponentProps
进行撰写:
export const enhance = compose<UserProps, ComponentProps>(
这是因为,查看 compose
的类型定义export function compose<TInner, TOutter>(
...functions: Function[]
): ComponentEnhancer<TInner, TOutter>;
我作为 TInner
通过 UserProps
,但是 TOutter
增强组件的空对象导致了错误。
编辑:
为了扩展答案,TOutter
是外部组件的类型,在本例中是将接收名称道具的类型,即 index.tsx
中使用的 <User />
组件。 TInner
期望内部组件的类型将接收使用重组创建的所有道具,在本例中为 ./components/User.tsx
中的 User
组件。