如何在类组件中使用Redux Toolkit Query钩子?
在类组件中使用RTK Query的实现方案
针对你的大型类组件代码库迁移需求,RTK Query虽然主打函数组件的钩子,但完全可以通过手动dispatch action和从Redux store直接读取缓存状态来适配类组件,具体实现如下:
一、触发请求(对应函数组件的钩子自动触发)
RTK Query的每个接口端点(endpoint)都会生成一个initiate方法,用于创建触发请求的action。你可以在componentDidMount中dispatch这个action来启动请求,同时建议保存请求引用以在组件卸载时取消,避免内存泄漏。
示例代码:
import { postsApi } from './path/to/your/apiSlice'; class PostList extends React.Component { componentDidMount() { // 触发getPosts请求,保存请求实例用于后续取消 this.requestPromise = this.props.dispatch( postsApi.endpoints.getPosts.initiate() ); } componentWillUnmount() { // 取消未完成的请求,忽略取消带来的错误 this.requestPromise?.unwrap().catch(() => {}); this.requestPromise?.abort(); } // ...其他组件逻辑 }
二、读取状态(对应函数组件钩子返回的data/loading等状态)
RTK Query的所有请求缓存和状态都存在Redux store的api切片下(若自定义了api切片key则用对应名称)。你可以通过connect高阶组件将需要的状态映射到类组件的props中。
核心状态读取规则:
- 数据:
state.api.queries['请求唯一标识']?.data - 加载状态:
state.api.queries['请求唯一标识']?.status === 'pending' - 错误状态:
state.api.queries['请求唯一标识']?.status === 'rejected' - 成功状态:
state.api.queries['请求唯一标识']?.status === 'fulfilled'
其中请求唯一标识的格式为端点名称(参数JSON字符串),无参数时为端点名称(undefined)。
示例代码:
import { connect } from 'react-redux'; import { postsApi } from './path/to/your/apiSlice'; // 映射store状态到组件props const mapStateToProps = (state) => { // 获取getPosts请求的缓存条目 const postsQuery = state.api.queries['getPosts(undefined)']; return { posts: postsQuery?.data, isLoading: postsQuery?.status === 'pending', isError: postsQuery?.status === 'rejected', isSuccess: postsQuery?.status === 'fulfilled', error: postsQuery?.error }; }; // 用connect包裹类组件,注入状态和dispatch export default connect(mapStateToProps)(PostList);
三、带参数的请求处理
如果请求需要动态参数(比如根据ID获取单篇文章),只需在initiate中传入参数,并调整状态读取的唯一标识:
// 触发带参数的请求 componentDidMount() { const { postId } = this.props; this.requestPromise = this.props.dispatch( postsApi.endpoints.getPost.initiate(postId) ); } // mapStateToProps中读取对应状态 const mapStateToProps = (state, ownProps) => { const queryKey = `getPost(${ownProps.postId})`; const postQuery = state.api.queries[queryKey]; return { post: postQuery?.data, isLoading: postQuery?.status === 'pending' }; };
四、针对大量类组件的复用优化
考虑到你有271个类组件,重复编写上述逻辑会非常繁琐,建议封装一个高阶组件(HOC)统一处理RTK Query的请求触发和状态映射:
import { connect } from 'react-redux'; // 封装通用RTK Query HOC const withRTKQuery = (endpoint, getArgs = () => []) => { return (Component) => { // 统一映射状态逻辑 const mapStateToProps = (state, ownProps) => { const args = getArgs(ownProps); const queryKey = `${endpoint.name}(${JSON.stringify(args)})`; const query = state.api.queries[queryKey]; return { data: query?.data, isLoading: query?.status === 'pending', isError: query?.status === 'rejected', isSuccess: query?.status === 'fulfilled', error: query?.error }; }; const ConnectedComponent = connect(mapStateToProps)(Component); // 统一请求触发和清理逻辑 return class extends React.Component { componentDidMount() { const args = getArgs(this.props); this.requestPromise = this.props.dispatch(endpoint.initiate(...args)); } componentWillUnmount() { this.requestPromise?.unwrap().catch(() => {}); this.requestPromise?.abort(); } render() { return <ConnectedComponent {...this.props} />; } }; }; }; // 使用示例:无参数请求 export default withRTKQuery(postsApi.endpoints.getPosts)(PostList); // 使用示例:带参数请求 export default withRTKQuery( postsApi.endpoints.getPost, (props) => [props.postId] )(PostDetail);
内容的提问来源于stack exchange,提问作者Probosckie
相关产品推荐
相关产品推荐

