How do I call props.history.push() if I'm destructuring my props?

406 Views Asked by At

If I've got a function that creates a confirm popup when you click the back button, I want to save the state before navigating back to the search page. The order is a bit odd, there's a search page, then a submit form page, and the summary page. I have replace set to true in the reach router so when I click back on the summary page it goes to the search page. I want to preserve the history and pass the state of the submitted data into history, so when I click forward it goes back to the page without error.

I've looked up a bunch of guides and went through some of the docs, I think I've got a good idea of how to build this, but in this component we're destructuring props, so how do I pass those into the state variable of history?

export const BaseSummary = ({successState, children}: BaseSummaryProps) => {
  let ref = createRef();
  const [pdf, setPdf] = useState<any>();
  const [finishStatus, setfinishStatus] = useState(false);

  const onBackButtonEvent = (e) => {
    e.preventDefault();
    if (!finishStatus) {
      if (window.confirm("Your claim has been submitted, would you like to exit before getting additional claim information?")) {
        setfinishStatus(true);
        props.history.push(ASSOCIATE_POLICY_SEARCH_ROUTE); // HERE
      } else {
        window.history.pushState({state: {successState: successState}}, "", window.location.pathname);
        setfinishStatus(false);
      }
    }
  };

  useEffect(() => {
    window.history.pushState(null, "", window.location.pathname);
    window.addEventListener('popstate', onBackButtonEvent);
    return () => {
      window.removeEventListener('popstate', onBackButtonEvent);  
    };
  }, []);

Also I'm not passing in the children var because history does not clone html elements, I just want to pass in the form data that's returned for this component to render the information accordingly

2

There are 2 best solutions below

2
On

first of all, I think you need to use "useHistory" to handling your hsitry direct without do a lot of complex condition, and you can check more from here

for example:
 let history = useHistory();

  function handleClick() {
    history.push("/home");
  }

now, if you need to pass your history via props in this way or via your code, just put it in function and pass function its self, then when you destruct you just need to write your function name...for example:

  function handleClick() {
    history.push("/home");
  }

  <MyComponent onClick={handleClick} />

  const MyComponent = ({onClick}) => {....}
0
On

I fixed it. We're using reach router, so everytime we navigate in our submit forms pages, we use the replace function like so: {replace: true, state: {...stateprops}}. Then I created a common component that overrides the back button functionality, resetting the history stack every time i click back, and using preventdefault to stop it from reloading the page. Then I created a variable to determine whether the window.confirm was pressed, and when it is, I then call history.back().

In some scenarios where we went to external pages outside of the reach router where replace doesn't work, I just used window.history.replaceStack() before the navigate (which is what reach router is essentially doing with their call).

Anyways you wrap this component around wherever you want the back button behavior popup to take effect, and pass in the successState (whatever props you're passing into the current page you're on) in the backButtonBehavior function.

Here is my code:

import React, {useEffect, ReactElement} from 'react';
import { StateProps } from '../Summary/types';

export interface BackButtonBehaviorProps {
  children: ReactElement;
  successState: StateProps;
}

let isTheBackButtonPressed = false;

export const BackButtonBehavior = ({successState, children}: BackButtonBehaviorProps) => {
  const onBackButtonEvent = (e: { preventDefault: () => void; }) => {
    e.preventDefault();

    if (!isTheBackButtonPressed) {
      if (window.confirm("Your claim has been submitted, would you like to exit before getting additional claim information?")) {
        isTheBackButtonPressed = true;
        window.history.back();
      } else {
        isTheBackButtonPressed = false;
        window.history.pushState({successState: successState}, "success page", window.location.pathname); // When you click back (this refreshes the current instance)
      }
    } else {
      isTheBackButtonPressed = false;
    }
  };

  useEffect(() => {
    window.history.pushState(null, "", window.location.pathname);
    window.addEventListener('popstate', onBackButtonEvent);
    return () => {
      window.removeEventListener('popstate', onBackButtonEvent);  
    };
  }, []);

  return (children);
};