我正在使用React / Redux和TypeScript转换。我希望我的导航菜单从状态读取并保持其自己的迷你状态。
NavMenu.tsx:
import * as React from 'react';
import { NavLink, Link, RouteComponentProps } from 'react-router-dom';
import { connect } from 'react-redux';
import { ApplicationState } from '../store';
import * as NavigationStore from '../store/Navigation';
type NavigationProps =
NavigationStore.NavigationState
& typeof NavigationStore.actionCreators;
class NavMenu extends React.Component<NavigationProps, {}> {
public render() {
return (
<nav className='main-nav'>
<ul className={`nav-standard`}>
<li>
<NavLink exact to={'/'} activeClassName='active'>
Home
</NavLink>
</li>
<li>
<NavLink to={'/learn'} activeClassName='active'>
Learn
</NavLink>
</li>
<li>
<NavLink to={'/blog'} activeClassName='active'>
Blog
</NavLink>
</li>
</ul>
<div className='nav-small'>
<button type='button' className='navbar-toggle' onClick={() => { this.props.toggle() } }>
<span className='screen-reader-content'>Toggle Navigation</span>
<i className='fa fa-bars'></i>
</button>
</div>
</nav>
);
}
}
export default connect(
(state: ApplicationState) => state.navigation,
NavigationStore.actionCreators
)(NavMenu) as typeof NavMenu;
以下是我尝试渲染导航栏的方法,Layout.tsx:
import * as React from 'react';
import NavMenu from './NavMenu';
export class Layout extends React.Component<{}, {}> {
public render() {
return <div>
<NavMenu />
{ this.props.children }
</div>;
}
}
我收到了打字稿格式错误:
TS2322: Type '{}' is not assignable to type 'IntrinsicAttributes & IntrinsicClassAttributes<NavMenu> & Readonly<{ children?: ReactNode; }> & R...'.
Type '{}' is not assignable to type 'Readonly<NavigationProps>'.
Property 'expanded' is missing in type '{}'.
这不是connect()函数的目的吗?要自动将状态和操作映射到组件?这通常是我没有将props传递给组件时所得到的错误(不使用connect())。
修改
当我彻底传递NavigationProps
类型所需的所有属性时,它确实有效:
import * as React from 'react';
import NavMenu from './NavMenu';
export class Layout extends React.Component<{}, {}> {
public render() {
return <div>
<NavMenu expanded={false} expand={Navigation.actionCreators.expand} constrict={Navigation.actionCreators.constrict} toggle={Navigation.actionCreators.toggle} />
{ this.props.children }
</div>;
}
}
后代的 Navigation.ts
(新导入):
import { Action, Reducer } from 'redux';
export interface NavigationState {
expanded: boolean;
};
interface ExpandNavigationAction { type: 'EXPAND_NAVIGATION' }
interface ConstrictNavigationAction { type: 'CONSTRICT_NAVIGATION' }
interface ToggleNavigationAction { type: 'TOGGLE_NAVIGATION' }
type KnownAction = ExpandNavigationAction
| ConstrictNavigationAction
| ToggleNavigationAction;
export const actionCreators = {
expand: () => <ExpandNavigationAction>{ type: 'EXPAND_NAVIGATION' },
constrict: () => <ConstrictNavigationAction>{ type: 'CONSTRICT_NAVIGATION'
},
toggle: () => <ToggleNavigationAction>{ type: 'TOGGLE_NAVIGATION' }
};
export const reducer: Reducer<NavigationState> = (state: NavigationState,
action: KnownAction) => {
switch (action.type) {
case 'EXPAND_NAVIGATION':
return { expanded: true };
case 'CONSTRICT_NAVIGATION':
return { expanded: false };
case 'TOGGLE_NAVIGATION':
return { expanded: !state.expanded };
default:
const exhaustiveCheck: never = action;
}
return state || { expanded: false };
}
即使这成功转化,我这样做的目的是避免写出这样冗长的标记。我的印象是connect()方法的重点是通过mapper方法简单轻松地将状态下的正确属性传递给子组件。
答案 0 :(得分:1)
不要将connect()
的结果转换为typeof NavMenu
。当你这样做时,你告诉TS该组件希望将NavigationProps
对象作为属性传入。因此,当您没有传递任何属性时,您会收到错误。
由connect()
创建的包装组件没有必需的属性。