如何在TypeScript+Apollo中为React类组件添加类型化SignIn Mutation方法
使用react-apollo为React类组件添加类型化的signIn方法
针对你的需求,我整理了完整的实现方案,包含TypeScript类型化版本和JavaScript简化版本,方便你根据项目情况选择:
TypeScript类型化实现(推荐)
如果你的项目用TypeScript,我们可以通过定义明确的类型来让signIn方法获得完整的类型提示和校验:
import React from 'react'; import SignInMutation from '~/mutations/SignInMutation.gql'; import { graphql, MutationFunc } from 'react-apollo'; // 定义登录需要的变量类型 interface SignInVariables { email: string; password: string; } // 定义Mutation返回的数据结构类型 interface SignInResponse { signIn: { token: { accessToken: string; accessTokenExpiresOn: string; }; }; } // 定义组件接收的props类型 interface SignInComponentProps { signIn: (variables: SignInVariables) => Promise<SignInResponse>; } class SignInComponent extends React.Component<SignInComponentProps> { handleLogin = async (email: string, password: string) => { try { const loginResult = await this.props.signIn({ email, password }); // 登录成功后的逻辑,比如存储token到本地 localStorage.setItem('authToken', loginResult.signIn.token.accessToken); console.log('登录成功,token有效期:', loginResult.signIn.token.accessTokenExpiresOn); } catch (error) { // 处理登录失败,比如提示用户账号密码错误 alert(`登录失败: ${error.message}`); } }; render() { return ( <div className="login-form"> {/* 这里可以添加邮箱密码输入框,绑定到state后调用handleLogin */} <button onClick={() => this.handleLogin('user@example.com', '123456')}> 登录 </button> </div> ); } } // 用graphql高阶组件包装组件,映射出类型化的signIn方法 export default graphql(SignInMutation, { props: ({ mutate }: { mutate: MutationFunc<SignInResponse, SignInVariables> }) => ({ signIn: async (variables: SignInVariables) => { const response = await mutate({ variables }); // 额外判断返回数据是否存在,避免空值问题 if (!response.data) { throw new Error('登录请求未返回有效数据'); } return response.data; }, }), })(SignInComponent);
JavaScript简化实现
如果你的项目用纯JavaScript,可以去掉类型定义部分,简化代码:
import React from 'react'; import SignInMutation from '~/mutations/SignInMutation.gql'; import { graphql } from 'react-apollo'; class SignInComponent extends React.Component { handleLogin = async (email, password) => { try { const loginResult = await this.props.signIn({ email, password }); localStorage.setItem('authToken', loginResult.signIn.token.accessToken); console.log('登录成功'); } catch (error) { alert(`登录失败: ${error.message}`); } }; render() { return ( <div className="login-form"> <button onClick={() => this.handleLogin('user@example.com', '123456')}> 登录 </button> </div> ); } } export default graphql(SignInMutation, { props: ({ mutate }) => ({ signIn: (variables) => mutate({ variables }) .then(response => { if (!response.data) throw new Error('无返回数据'); return response.data; }), }), })(SignInComponent);
关键细节说明
- props映射逻辑:在
graphql的第二个参数中,我们通过props函数把原生的mutate方法包装成业务友好的signIn方法,直接接收登录所需的邮箱和密码变量。 - 错误处理:在包装后的
signIn方法里,我们做了额外的空值检查,避免后续操作出现未定义错误,同时统一抛出错误让组件层面处理。 - 装饰器语法:如果你习惯用装饰器(比如
@graphql(...)),只要你的项目编译环境支持(比如TypeScript开启experimentalDecorators,或Babel配置装饰器插件),可以把HOC包装改成装饰器形式:
@graphql(SignInMutation, { props: ({ mutate }: { mutate: MutationFunc<SignInResponse, SignInVariables> }) => ({ signIn: async (variables: SignInVariables) => { // 同上的signIn逻辑 }, }), }) class SignInComponent extends React.Component<SignInComponentProps> { // 组件内容 }
内容的提问来源于stack exchange,提问作者lifeiscontent
相关产品推荐
相关产品推荐

