Skip to content

useStepper hook's when method doesn't render any step when using only when to conditionally render a step #127

@Strangersknowme

Description

@Strangersknowme

Let me explain it a bit more with an example.

My requirement is that I want to conditionally render navigation icons at the top of the form depending on if either of the refundItems or exchangeItems are non-empty.

Here's rhw concerned code using stepper where const stepper=useStepper() and I want to conditonally render the icons:

const { refundItems: refundItemsList, exchangeItems: exchangeItemsList } =
    useContext(<contextapi>);

  // Icon mapping based on index
  const icons = { refundItems: RotateCcw, exchangeItems: Replace }; //Lucide dev icons

  // Helper to determine if a step is "completed"
  const isCompleted = (index) =>
    index < stepper.current.index || buttonDisabledState;

  const onlyRefund = useMemo(
    () => refundItemsList.length > 0 && exchangeItemsList.length === 0,
    [refundItemsList, exchangeItemsList]
  );
  const onlyExchange = useMemo(
    () => exchangeItemsList.length > 0 && refundItemsList.length === 0,
    [refundItemsList, exchangeItemsList]
  );

  const conditionalStepId = useMemo(() => {
    if (onlyRefund) {
      return ["refundItems", true];
    }
    if (onlyExchange) {
      return ["exchangeItems", true];
    }
    return ["", false];
  }, [onlyRefund, onlyExchange]);

  const ConditionalIcon = useMemo(() => {
    const stepIdName = conditionalStepId[0];
    const icon = icons[stepIdName];
    return icon;
  }, [conditionalStepId]);

  return (
    <>
      {stepper.when([...conditionalStepId], () => (
        <>
          <Separator
            className={`flex-1 h-[2px] ${
              isCompleted(0) ? "bg-green-200" : "bg-neutral-200"
            }`}
          />
          <li className="flex items-center px-2">
            <div
              className={`flex w-10 h-10 bg-neutral-200 items-center justify-center rounded-full shadow-xl ${
                isCompleted(0) ? "bg-green-200" : ""
              }`}
            >
              {isCompleted(0) ? (
                <Check className="w-5 h-5" />
              ) : (
                <ConditionalIcon className="w-5 h-5" />
              )}
            </div>
          </li>
          <Separator
            className={`flex-1 h-[2px] ${
              isCompleted(0) ? "bg-green-200" : "bg-neutral-200"
            }`}
          />
        </>
      ))}
    </>
  );

As you can see from the code above, that I want to render the conditional icon depending on the if either of the list's is non-empty then I should be shown that component, right?

That's not what's happening. I think the reason why it is not rendering the exchangeItems step for my case is that since it is the 2nd step and the current step will always remain refundItems step as I am not going to the next step, it doesn't even render that step.

I am duct taping it to solve this by triggering a side effect to go to that step which isn't ideal. I was hoping if there was a way to dynamically render steps for dynamic forms. I couldn't find anything in the documentation and the documentation of when method doesn't make it clear.

This would especially be useful for dynamic steps.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions