Ecosyste.ms: Awesome

An open API service indexing awesome lists of open source software.

Awesome Lists | Featured Topics | Projects

https://github.com/pocesar/react-native-stager

A performant wizard-like multi stages component for React Native without a router
https://github.com/pocesar/react-native-stager

performant react react-native react-native-component typescript wizard wizard-steps

Last synced: 17 days ago
JSON representation

A performant wizard-like multi stages component for React Native without a router

Awesome Lists containing this project

README

        

[![Build Status](https://travis-ci.org/pocesar/react-native-stager.svg?branch=master)](https://travis-ci.org/pocesar/react-native-stager) [![Coverage Status](https://coveralls.io/repos/github/pocesar/react-native-stager/badge.svg?branch=master)](https://coveralls.io/github/pocesar/react-native-stager?branch=master) [![npm version](https://badge.fury.io/js/react-native-stager.svg)](https://badge.fury.io/js/react-native-stager)

# react-native-stager

A performant wizard-like multi stages component for React Native without a router

## Why?

Using a router solution to create a multi-step wizard-like interface is good, but sometimes you want
to keep all your state in just one parent component without having to rely on `redux` for example,
enter the `Stager`

## How?

```jsx
import React from 'react'
import { View, TouchableOpacity, Text } from 'react-native'
import Stager, { Stage } from 'react-native-stager'

class MyWizard extends React.Component {
render() {
return (
{
// stage == step 1 || step 2
// direction = 1 = next | -1 = prev | 0 = reset / initial
}}>
true}>
{({ instance, context }) => (


{'Hello'}


)}

this.setState({ loaded: true }, cb)}>
{() => (
{'World'}
)}


)
}
}

export default MyWizard
```

## Components and API

`Stager`

The root component that will hold the steps. Accepts an `onChange` prop that receives the transitioning stage name and the direction (-1 = prev / 1 = next / 0 = reset/initial).
Can be safely nested.

```tsx
{
// do something nice
}}>

```

`Stage`

Need to set inside `Stager`. Can use `continue`, `noPrevious` and `loaded` props.
Notice that the children must always be a function. The `key` prop is required.

It receives an object with `instance` (this current `Stage`) and
`context` (the current `Stager`)

```tsx


{({ instance, context }) => (
{'This is step 1'}
)}

```

When using `continue`, you always need to signal to the `Stage` that it should re-evaluate the
`continue` function, to see if you're able to continue. This is so the component doesn't
re-render everytime everytime a children changes.

```tsx

this.state.canContinue}
>
{({ instance, context }) => (

{'This is step 1'}
{
this.setState({
canContinue: true
}, instance.refresh)
}} />

)}

this.setState({ canContinue: false }, cb)}
continue={() => this.state.canContinue}
>
{({ instance, context }) => (

{'This is step 1'}
{
this.setState({
canContinue: true
}, instance.refresh)
}} />

)}

```

`StageButtons`

The internal implementation of the StageButtons are merely for a quick prototype standpoint (to get the stage going),
and you should style if using your own. It doesn't matter where you put them, they will always be below the current
active stage. Notice that you CAN set the style to use `position: absolute` and place it anywhere in the stage.

```tsx


{({ context }) => (




)}

```

`StageProgress`

The same thing with `StageButtons`, it's just an ugly placeholder to show functionality. Replace it with your own

```tsx


{({ context }) => (



{context.state.stages.map((stage, index) => (

)
)}




)}

```

## Caveats

* Since you need to use function children, your `shouldComponentUpdate` might go crazy. To counter that
assign a class member for your function that returns your component
* The default progress and prev / next buttons are dull, and most likely won't match your application
style. For that, use `StageProgress` and `StageButtons` wherever you feel like it
* Children `Stage` won't automatically update (since `Stage` has `shouldComponentUpdate` to return `false`), so you
need, on the `instance`, to call `refresh` whenever you need to update your prev / next buttons

## License

MIT