Skip to content

Wizard.useStep#

Import#

import { Wizard } from '@dnb/eufemia/extensions/forms'
// Use Wizard.useStep

Description#

Wizard.useStep is a React Hook that returns Wizard.Context parameters such as totalSteps, activeIndex or the setActiveIndex handler.

Relevant links#

import { Form, Wizard } from '@dnb/eufemia/extensions/forms'
function Step1() {
const { totalSteps, activeIndex, setActiveIndex } = Wizard.useStep()
return <Wizard.Step>...</Wizard.Step>
}
function MyForm() {
return (
<Form.Handler>
<Wizard.Container>
<Step1 />
</Wizard.Container>
</Form.Handler>
)
}

You can also connect the hook with the Wizard.Container via an id (string, function, object or React Context as the reference). This lets you render the hook outside of the context:

import { Form } from '@dnb/eufemia/extensions/forms'
const myContainerId = 'unique-id' // or a function, object or React Context reference
function Sidecar() {
const { activeIndex, setActiveIndex } = Wizard.useStep(myContainerId)
}
function MyForm() {
return (
<Form.Handler>
<Sidecar />
<Wizard.Container id={myContainerId}>...</Wizard.Container>
</Form.Handler>
)
}

EditButton#

In order to navigate to a new step when using setActiveIndex you can use the Wizard.EditButton component.

Listen to step change#

You can also use the onStepChange event to listen to a step change.

function MyStep() {
// Ensure to use "useCallback" or keep the function outside of the component to avoid memory leaks
const onStepChange = React.useCallback(
(index, mode, { preventNavigation }) => {
// Do something with the step change
},
[]
)
Wizard.useStep(undefined, { onStepChange })
return <Wizard.Step>...</Wizard.Step>
}

Demos#

const Step1 = () => {
  const { activeIndex, setActiveIndex } = Wizard.useStep()
  return (
    <Button
      variant="secondary"
      onClick={() => {
        setActiveIndex(activeIndex + 1)
      }}
    >
      Next
    </Button>
  )
}
const Step2 = () => {
  const { activeIndex, setActiveIndex } = Wizard.useStep()
  return (
    <Button
      variant="secondary"
      onClick={() => {
        setActiveIndex(activeIndex + 1)
      }}
    >
      Next
    </Button>
  )
}
const Step3 = () => {
  const { activeIndex, setActiveIndex } = Wizard.useStep()
  return (
    <Button
      variant="secondary"
      onClick={() => {
        setActiveIndex(activeIndex - 1)
      }}
    >
      Previous
    </Button>
  )
}
render(
  <Provider
    StepIndicator={{
      overviewTitle: 'Step hook wizard steps',
    }}
  >
    <Wizard.Container mode="loose">
      <Wizard.Step aria-label="Step hook wizard: Step 1" title="Step 1">
        <Step1 />
      </Wizard.Step>

      <Wizard.Step aria-label="Step hook wizard: Step 2" title="Step 2">
        <Step2 />
      </Wizard.Step>

      <Wizard.Step aria-label="Step hook wizard: Step 3" title="Step 3">
        <Step3 />
      </Wizard.Step>
    </Wizard.Container>
  </Provider>
)

Outside of context#

Step 1
const RenderBefore = () => {
  const { activeIndex, setActiveIndex } = Wizard.useStep('unique-id')
  return (
    <Button
      variant="secondary"
      onClick={() => {
        setActiveIndex(activeIndex - 1)
      }}
    >
      Previous
    </Button>
  )
}
const RenderAfter = () => {
  const { activeIndex, setActiveIndex } = Wizard.useStep('unique-id')
  return (
    <Button
      variant="secondary"
      onClick={() => {
        setActiveIndex(activeIndex + 1)
      }}
    >
      Next
    </Button>
  )
}
render(
  <Flex.Stack>
    <RenderBefore />
    <Provider
      StepIndicator={{
        overviewTitle: 'External step controls wizard steps',
      }}
    >
      <Wizard.Container id="unique-id" mode="loose">
        <Wizard.Step
          aria-label="External step controls wizard: Step 1"
          title="Step 1"
        >
          <output>Step 1</output>
        </Wizard.Step>

        <Wizard.Step
          aria-label="External step controls wizard: Step 2"
          title="Step 2"
        >
          <output>Step 2</output>
        </Wizard.Step>

        <Wizard.Step
          aria-label="External step controls wizard: Step 3"
          title="Step 3"
        >
          <output>Step 3</output>
        </Wizard.Step>
      </Wizard.Container>
    </Provider>
    <RenderAfter />
  </Flex.Stack>
)

Using onStepChange event#

const onStepChange1 = (index, mode, { preventNavigation }) => {
  console.log(
    'onStepChange from Step1:',
    index,
    mode,
    typeof preventNavigation
  )
}
const onStepChange2 = (index, mode, { preventNavigation }) => {
  console.log(
    'onStepChange from Step2:',
    index,
    mode,
    typeof preventNavigation
  )
}
const onStepChange3 = (index, mode, { preventNavigation }) => {
  console.log(
    'onStepChange from Step3:',
    index,
    mode,
    typeof preventNavigation
  )
}
const Step1 = () => {
  Wizard.useStep(undefined, {
    onStepChange: onStepChange1,
  })
  return (
    <Wizard.Step
      aria-label="Step change hook wizard: Step 1"
      title="Step 1"
    >
      <Wizard.Buttons />
    </Wizard.Step>
  )
}
const Step2 = () => {
  Wizard.useStep(undefined, {
    onStepChange: onStepChange2,
  })
  return (
    <Wizard.Step
      aria-label="Step change hook wizard: Step 2"
      title="Step 2"
    >
      <Wizard.Buttons />
    </Wizard.Step>
  )
}
const Step3 = () => {
  Wizard.useStep(undefined, {
    onStepChange: onStepChange3,
  })
  return (
    <Wizard.Step
      aria-label="Step change hook wizard: Step 3"
      title="Step 3"
    >
      <Wizard.Buttons />
    </Wizard.Step>
  )
}
render(
  <Provider
    StepIndicator={{
      overviewTitle: 'Step change hook wizard steps',
    }}
  >
    <Wizard.Container mode="loose">
      <Step1 />
      <Step2 />
      <Step3 />
    </Wizard.Container>
  </Provider>
)
Suggest an edit