Search code examples
reduxredux-toolkit

Using Redux Toolkit Query hooks in class components


We have a really large codebase with 271 class components and the old redux (not redux toolkit).

We are in the process of migrating to redux toolkit - and adoption RTK-Query as our async state manager. We will migrate redux-saga based functionality to rtk-query and trim our reducers.

For functional components it's very easy to do both things

  1. get data, loading state
  2. dispatch the action to ask for this data.
 const {data: posts, isLoading, isError, isSuccess } = usePosts();

But how do I do this in a class based component...

componentDidMount(){
  //what to dispatch here ?
}

render(){
   const {data: posts, isLoading, isError, isSuccess } = fromWhichPlace;
}


Solution

  • We specifically cover this topic in our docs:

    Per those pages, you'd need to do something along the lines of:

    
    const mapState = (
      state: RootState,
      ownProps: RouteComponentProps<{ id: string }>
    ) => ({
      id: Number(ownProps.match.params.id),
      post: endpoints.getPost.select(Number(ownProps.match.params.id))(state),
      updatePostState: endpoints.updatePost.select(ownProps.match.params.id)(state), // TODO: make selectors work with the requestId of the mutation?
      deletePostState: endpoints.updatePost.select(ownProps.match.params.id)(state)
    });
    
    const mapDispatch = {
      getPost: endpoints.getPost.initiate,
      updatePost: endpoints.updatePost.initiate,
      deletePost: endpoints.deletePost.initiate
    };
    
    const connector = connect(mapState, mapDispatch);
    type PostDetailProps = ConnectedProps<typeof connector> & RouteComponentProps;
    
    export class PostDetailComp extends React.Component<PostDetailProps> {
      state = {
        isEditing: false
      };
    
      componentDidMount() {
        const { id, getPost } = this.props;
        getPost(id);
      }
    
      componentDidUpdate(prevProps: PostDetailProps) {
        const { id, getPost } = this.props;
        if (id !== prevProps.id) {
          getPost(id);
        }
      }
    
      render() {
        const { isEditing } = this.state;
        const {
          // state
          id,
          post: { data: post, isLoading: isPostLoading },
          updatePostState: { isLoading: isUpdateLoading },
          deletePostState: { isLoading: isDeleteLoading },
    
          // actions
          updatePost,
          deletePost
        } = this.props;
    
        // snip rendering logic
    }
    
    export const PostDetail = connector(PostDetailComp);
    

    However, we would strongly recommend that you convert these components to function components instead, and use the auto-generated query hooks! It will be much simpler and easier to use, and the hooks have a lot of built-in functionality that will be hard to replicate by hand in class components.