NextStep - Lightweight Next.js Onboarding Library Logo

Callbacks for React

NextStep provides a powerful callbacks system that allows you to execute custom code at various points during a tour. This enables you to create dynamic, interactive tours that respond to user actions.

Available Callbacks

NextStep supports the following callbacks that you can use to customize your tour behavior:

onStart

Called when a tour starts. Receives the tour name as a parameter.

onStart: (tourName: string | null) => {
  console.log(`Tour ${tourName} started`);
  // Track analytics, set user state, etc.
}

onComplete

Called when a tour is completed. Receives the tour name as a parameter.

onComplete: (tourName: string | null) => {
  console.log(`Tour ${tourName} completed`);
  // Update user preferences, show completion message, etc.
}

onSkip

Called when a user skips a tour. Receives the step index and tour name as parameters.

onSkip: (step: number, tourName: string | null) => {
  console.log(`Tour ${tourName} skipped at step ${step}`);
  // Log skip event, offer to resume later, etc.
}

onStepChange

Called when the current step changes. Receives the step index and tour name as parameters.

onStepChange: (step: number, tourName: string | null) => {
  console.log(`Tour ${tourName} moved to step ${step}`);
  // Update UI, trigger animations, etc.
}

Using Callbacks

You can provide callbacks when initializing the NextStep component:

// In your root component
import { NextStepProvider, NextStepReact } from 'nextstepjs';
import steps from './steps';

function App() {
  return (
    <NextStepProvider>
      <NextStepReact 
        steps={steps}
        onStart={(tourName) => {
          console.log(`Tour ${tourName} started`);
        }}
        onComplete={(tourName) => {
          console.log(`Tour ${tourName} completed`);
        }}
        onSkip={(step, tourName) => {
          console.log(`Tour ${tourName} skipped at step ${step}`);
        }}
        onStepChange={(step, tourName) => {
          console.log(`Step changed to ${step} in ${tourName}`);
        }}
      >
        <YourAppContent />
      </NextStepReact>
    </NextStepProvider>
  );
}

Practical Examples

Tracking User Progress

Use callbacks to track user progress through your onboarding tour:

// Track user progress with analytics
const trackProgress = {
  onStart: (tourName) => {
    analytics.track('tour_started', { tourName });
  },
  onStepChange: (step, tourName) => {
    analytics.track('tour_step_viewed', { 
      tourName, 
      stepIndex: step,
      stepName: `${tourName}_step_${step}`
    });
  },
  onComplete: (tourName) => {
    analytics.track('tour_completed', { tourName });
    // Update user profile to mark onboarding as complete
    updateUserProfile({ onboardingComplete: true });
  },
  onSkip: (step, tourName) => {
    analytics.track('tour_skipped', { tourName, stepIndex: step });
  }
};

// Then use it in your NextStep component
<NextStepReact 
  steps={steps}
  {...trackProgress}
>
  {children}
</NextStepReact>

Form Validation

Use the onStepChange callback to validate form inputs when a user moves to a new step:

// Form validation when step changes
const formValidation = {
  onStepChange: (step, tourName) => {
    // Validate the previous step's inputs
    if (step === 2 && tourName === 'onboardingTour') {
      const usernameField = document.getElementById('username');
      if (!usernameField || !usernameField.value) {
        // Log validation failure
        console.warn('Username field was not completed');
      }
    }
    
    if (step === 3 && tourName === 'onboardingTour') {
      const emailField = document.getElementById('email');
      if (!emailField || !validateEmail(emailField.value)) {
        // Log validation failure
        console.warn('Email field was not completed or is invalid');
      }
    }
  }
};

// Then use it in your NextStep component
<NextStepReact 
  steps={steps}
  {...formValidation}
>
  {children}
</NextStepReact>

Dynamic Content

Use the onStepChange callback to update UI elements based on the current step:

// Dynamic content based on current step
const [highlightedSection, setHighlightedSection] = useState(null);

const dynamicContent = {
  onStepChange: (step, tourName) => {
    // Update UI based on the current step
    if (tourName === 'featureTour') {
      switch(step) {
        case 0:
          setHighlightedSection('dashboard');
          break;
        case 1:
          setHighlightedSection('sidebar');
          break;
        case 2:
          setHighlightedSection('settings');
          break;
        default:
          setHighlightedSection(null);
      }
    }
  },
  onComplete: () => {
    // Reset UI when tour ends
    setHighlightedSection(null);
  },
  onSkip: () => {
    // Reset UI when tour is skipped
    setHighlightedSection(null);
  }
};

// Then use it in your NextStep component
<NextStepReact 
  steps={steps}
  {...dynamicContent}
>
  {children}
</NextStepReact>

Note: Callbacks must be defined in a client component. Ensure that your component is using 'use client' at the top.