Pular para o conteúdo principal

Receitas

Lembrando o que já foi visto

A lib não guarda esse registro. Ela mostra o tour, e se o tour deve aparecer é decisão sua — assim nenhum engine de storage entra no seu bundle à força.

O autoStart é o portão, e ele inicia o tour no momento em que vira true, o que faz uma leitura assíncrona não custar nada.

import { MMKV } from 'react-native-mmkv';

const mmkv = new MMKV();

export const Scanner = () => {
const [seen, setSeen] = useState<boolean | null>(null);

useEffect(() => {
setSeen(mmkv.getBoolean('tour.scanner') ?? false);
}, []);

return (
<Cicerone.Provider
steps={STEPS}
autoStart={seen === false}
onStop={() => mmkv.set('tour.scanner', true)}
>
{/* targets */}
</Cicerone.Provider>
);
};

Enquanto seen for null a leitura ainda não chegou e o autoStart fica falso, então o tour nunca pisca antes de você saber a resposta. O AsyncStorage funciona igual.

Um botão de repetir

const { start } = useCicerone();

start() roda o tour sempre que você chamar. Limpar o seu próprio registro, se você mantiver um, é com você.

Deixar o usuário tocar no elemento destacado

Por padrão uma camada cobre a tela e qualquer toque avança, que é o que a maioria dos onboardings quer. Quando o ponto do passo é o usuário realmente apertar a coisa:

<Cicerone.Provider steps={STEPS} allowTargetInteraction>

Aí quatro faixas cercam o furo em vez de uma camada inteira, e o alvo continua vivo.

Use overlayPress="none" se o toque não deve fazer nada e os botões do card são o único caminho.

Acompanhando o tour

<Cicerone.Provider
steps={STEPS}
onStart={() => analytics.track('tour_started')}
onStepChange={(index, step) => analytics.track('tour_step', { index, id: step.id })}
onStop={(reason) => analytics.track('tour_ended', { reason })}
/>

O onStop diz qual dos três aconteceu: finished, skipped, ou manual se você chamou stop(). Ele dispara uma vez, quando o tour acaba, não quando a animação de saída termina.

Forçando o lado do card

O card escolhe o lado que tem espaço. Quando você sabe melhor:

{ id: 'header-action', title: '...', text: '...', placement: 'bottom' }

Colocando um blur atrás do furo

O renderBackdrop desenha dentro do recorte, embaixo do scrim. A lib não traz blur, então use o que seu app já tem.

import { BlurView } from 'expo-blur';

<Cicerone.Provider
steps={STEPS}
renderBackdrop={() => <BlurView intensity={20} style={StyleSheet.absoluteFill} />}
/>;