converted class to hooks, getting Property 'then' does not exist on type '(dispatch: any) => Promise<void>'

Viewed 105

I'm new in react hooks, here converting from class(class version works) to hooks, i'm not sure if i have done it correctly because when using 'then' in hooks it says 'Property 'then' does not exist on type '(dispatch: any) => Promise'.ts(2339)'

this is class version which works:

import {
    getGraph,
    getFloorplan,
    changeActiveCamera,
} from "../redux/actions";

const mapStateToProps = (state) => {
  return {
    currentSite: state.selection.currentSite,
    currentCamera: state.selection.currentCamera,

  
  };
};

function mapDispatchToProps(dispatch) {
  return {
    getGraph: (site) => dispatch(getGraph(site)),
    getFloorplan: (site) => dispatch(getFloorplan(site)),
       changeActiveCamera: (site, id) => dispatch(changeActiveCamera(site, id)),

  };
}


loadGraph() {
    if (this.props.currentSite) {
      this.props.getFloorplan(this.props.currentSite.identif).then(() => {
        console.log("Fetched floorplan");

        this.props.getGraph(this.props.currentSite.identif).then(() => {
          console.log("Fetched model", this.props.realGraph.model);

          // new camera-related node & link status
          if (this.props.currentCamera) {
            this.props.changeActiveCamera(
              this.props.currentSite.identif,
              this.props.currentCamera.identif
            );
          }
        });
      });
    }
  }
this is what i have done in order to convert it :

  const dispatch = useDispatch();
  const currentSite = useSelector((state) => state.selection.currentSite);
  const currentCamera = useSelector((state) => state.selection.currentCamera);


const loadGraph = () => {
    if (currentSite) {
      dispatch(getFloorplan(currentSite.identif)).then(() => {
        console.log("Fetched floorplan");

        dispatch(getGraph(currentSite.identif)).then(() => {
          console.log("Fetched model", realGraph.model);

          // new camera-related node & link status
          if (currentCamera) {
            dispatch(
              changeActiveCamera(
                currentSite.identif,
                currentCamera.identif
              )
            );
          }
        });
      });
    }
  };

After seeing video shared in comment, i changed the code and getting new error: 'Uncaught RangeError: Maximum call stack size exceeded at getFloorplan ' my code:

   const currentSite = useSelector((state) =>      state.selection.currentSite);
   const currentCamera = useSelector((state) => state.selection.currentCamera);
   const getFloorplan = (site) => dispatch(getFloorplan(site));
   const getGraph = (site) => dispatch(getGraph(site));
   const changeActiveCamera = (site, id) =>
    dispatch(changeActiveCamera(site, id));
  
  const loadGraph = () => {
    if (currentSite) {
      getFloorplan(currentSite.identif).then(() => {
        console.log("Fetched floorplan");

        getGraph(currentSite.identif).then(() => {
          console.log("Fetched model", realGraph.model);

          // new camera-related node & link status
          if (currentCamera) {
            changeActiveCamera(
              currentSite.identif,
              currentCamera.identif
            );
          }
        });
      });
    }
  };

1 Answers

I highly doubt this simple solution will work, but here is my suggestions for refactors.

Please note that the way that your old class was written, that's not the recommended way of writing redux. Sure, the code will work, but it's not the "right" way in many people's opinions.

Refactor your actions

I would rather have my code written out like this :

YourComponent.tsx

const currentSite = useSelector((state) =>      state.selection.currentSite);
   const currentCamera = useSelector((state) => state.selection.currentCamera);
   const dispatch = useDispatch();

  const loadGraph = () => {
     useEffect(() => {
       if(currentSite)
          getFloorPlan(currenSite.identif);
      
     }, [ dispatch, currentSite.identif])
// dispatch is in the dependency array to stop make eslinter complain, you can remove it if you want, others are used to control the number of renders
    
  };

YourComponentActions.ts

// assuming you are using redux-thunk here
const getFloorplan = ( site : YourType ) => async dispatch => {
  console.log("Fetched floorplan");
  // remove await if getImage is a sync function, try with await first and remove if it doesn't fit
  const response = await getImage(`api/graph/${site}/floorplan`, GET_FLOORPLAN);
  dispatch(getGraph(response))
}

const getGraph = (site : YourType) => async dispatch => {
   console.log("Fetched model", realGraph.model);
   // new camera-related node & link status
   if (currentCamera) {
      changeActiveCamera(currentSite.identif,currentCamera.identif);
   }
}

const changeActiveCamera = ( site: YourType, param: YourAnotherType ) => async dispatch => {
 // your logic here
}
Related