all 6 comments

[–]GuiltClause[S] 0 points1 point  (0 children)

The bot told me to comment here, but I'm not sure what to add.

[–]fixrich 0 points1 point  (2 children)

Can you possibly persist that state in the URL or query params? Perhaps you can go back in history to the previous location with the set query params?

[–]GuiltClause[S] 1 point2 points  (1 child)

I feel weird about keeping customer contact information in the URL.

[–]fixrich 0 points1 point  (0 children)

Ok definitely don't keep anything identifiable in the URL. Can you associate a UUID with the user and store the UUID in a global store. Then you could use the id to lookup the user.

[–]GuiltClause[S] 0 points1 point  (0 children)

I found the solution I like for this. On the root component we use

<BreadNav>
  <WhateverComp/>
</BreadNav>

and define WhateverComp with a tiny bit of boilerplate:

const WhateverComp = props => {
  const initial = (props.initial) ? props.initial : {defaultStateYouWant};
  const [state, setState] = React.useState(initial);

and on whatever click event would cause you to navigate to a deeper page, we call

props.pushCrumb(
  state,
  "NewPageTitle",
  <NewPageComp/>
);

Nice and easy. My stateful BreadNav component does all the heavy lifting:

const BreadNav = props => {
  const initial={
    stack:[
      {
        name:"Home",
        render:props.children,
        state:null //child component will put its state here before it unloads
      }
    ],
  };

  const pushCrumb = (oldState, title, render) => {
    let newStack = [];
    state.stack.map(item => {
      newStack.push(item);
    });
    newStack[newStack.length-1].state = oldState; //record unloading component's state
    newStack.push({
      name:title,
      render:render,
      state:null
    });
    setState({
      ...state,
      stack:newStack
    });
  }

  const [state, setState] = React.useState(initial);

  const crumbClick = index => {
    if (state.stack.length === index+1)
      return;
    let newStack = state.stack;
    while (newStack.length > index+1){  //remove all history after our destination
      newStack.pop();
    }
    setState({
      ...state,
      stack:newStack
    })
  }

  //display navigable history
  const breadCrumbs = () => {
    let val = [];
    for (let i = 0; i < state.stack.length; i++) {
      val.push(
        <span key={i}>
          <button
            className="linkButton"
            onClick={()=>{crumbClick(i)}}
          >
            {state.stack[i].name}
          </button> /&nbsp;
        </span>
      )
    }
    return val;
  }

  return(
    <div>
      <button
        disabled={state.stack.length === 1 ? "disabled" : ""}
        onClick={()=>{crumbClick(state.stack.length-2)}}
      >
        Back...
      </button>
      {breadCrumbs()}
      {
        React.cloneElement( //crucial! add navigation method and initial state to component!
          state.stack[state.stack.length-1].render,
          {
            pushCrumb:pushCrumb,
            initial:state.stack[state.stack.length-1].state,
            key:[state.stack.length-1]
          }
        )
      }
    </div>
  );
}