React+TypeScript路由切换问题:Sign Out按钮无法跳转至Sign In页
问题:TypeScript下人脸识别应用路由切换失效(Sign Out按钮无法跳转)
我正在跟随ZTM课程开发人脸识别应用,用TypeScript替代JavaScript构建,全程避免使用any类型。刚接触TS,对细节掌握不足,现在遇到路由切换问题:点击Sign Out按钮无法跳转至Sign In页面,不像JS版本那样正常工作。
相关代码
App组件的接口与状态定义
interface IAppState { input: string, imageUrl: string, box: Object, route: string } class App extends Component<{title: string}, IAppState> { constructor(props: {title: string}) { super(props); this.state = { input: '', imageUrl: '', box: {}, route: 'signin' } }
App组件中路由变更相关代码
onRouteChange = ({route}) => { this.setState({route: route}); } render() { return ( <div className="App"> <ParticlesBg type="cobweb" bg={true} /> <Navigation onRouteChange={this.onRouteChange} /> { this.state.route === 'signin' ? <SignIn onRouteChange={this.onRouteChange}/> : <> <Logo /> <Rank /> <ImageLinkForm title='image link form' onInputChange={this.onInputChange} onButtonSubmit={this.onButtonSubmit} /> <FaceRecognition imageUrl={this.state.imageUrl}/> </> } </div> ); }
Navigation组件的Sign Out按钮代码
interface INavigationProps { onRouteChange: MouseEventHandler<HTMLInputElement>; } const Navigation: FC<INavigationProps> = ({ onRouteChange }) => { return ( <nav style={{ display: 'flex', justifyContent: 'flex-end' }}> <p onClick={() => onRouteChange('signin')} className='f3 link dim black underline pa3 pointer'>Sign Out</p> </nav> ); }
报错信息
Binding element 'route' implicitly has an 'any' typeType '({ route }: { route: any; }) => void' is not assignable to type 'MouseEventHandler<HTMLInputElement>'. Types of parameters '__0' and 'event' are incompatible. Property 'route' is missing in type 'MouseEvent<HTMLInputElement, MouseEvent>' but required in type '{ route: any; }'.Argument of type 'string' is not assignable to parameter of type 'MouseEvent<HTMLInputElement, MouseEvent>'
问题根源
三个错误本质都是路由变更函数的类型定义不匹配:
- App里的
onRouteChange错误地期望接收一个带route属性的对象,但实际上我们只需要传路由字符串 - Navigation组件把
onRouteChange定义成了点击事件处理函数(参数是MouseEvent),但App里的函数根本不接收事件对象 - 点击时传递字符串
signin给期望MouseEvent的函数,类型完全不兼容
修复方案
1. 定义严格的路由类型
先给路由定义字面量类型,避免使用宽泛的string,同时符合不使用any的要求:
// 可根据实际路由扩展,比如加上'register'等 type Route = 'signin' | 'home';
2. 修正App组件的onRouteChange方法
把原来解构对象的参数改成直接接收Route类型的字符串:
onRouteChange = (route: Route) => { this.setState({ route }); }
3. 修正App状态接口的route类型
让状态里的route和我们定义的Route类型一致:
interface IAppState { input: string; imageUrl: string; box: {}; // 后续可优化成具体的FaceBox接口,比如{ topRow: number; ... } route: Route; }
4. 修正Navigation组件的Props类型
把onRouteChange的类型改成接收Route字符串的函数,而不是点击事件处理函数:
import { FC } from 'react'; type Route = 'signin' | 'home'; interface INavigationProps { onRouteChange: (route: Route) => void; } const Navigation: FC<INavigationProps> = ({ onRouteChange }) => { return ( <nav style={{ display: 'flex', justifyContent: 'flex-end' }}> <p onClick={() => onRouteChange('signin')} className='f3 link dim black underline pa3 pointer'>Sign Out</p> </nav> ); }
5. 同步其他组件的调用(比如SignIn)
确保SignIn组件里调用onRouteChange时也传递Route类型的值,比如跳转到首页时用onRouteChange('home')。
优化建议(可选)
对于box的类型,目前用{}太宽泛,可以定义具体的接口来消除模糊类型:
interface FaceBox { topRow: number; bottomRow: number; leftCol: number; rightCol: number; } // 然后更新IAppState interface IAppState { // ...其他属性 box: FaceBox; }
内容的提问来源于stack exchange,提问作者Egor Kozhevnikov
相关产品推荐
相关产品推荐

