JSPM

@theuiteam/continuous-container

2.0.0
  • ESM via JSPM
  • ES Module Entrypoint
  • Export Map
  • Keywords
  • License
  • Repository URL
  • TypeScript Types
  • README
  • Created
  • Published
  • Downloads 697
  • Score
    100M100P100Q111788F
  • License MIT

State container with the known past, present, and the future

Package Exports

  • @theuiteam/continuous-container
  • @theuiteam/continuous-container/dist/es2015/index.js
  • @theuiteam/continuous-container/dist/es5/index.js

This package does not declare an exports field, so the exports above have been automatically detected and optimized by JSPM instead. If any package subpath is missing, it is recommended to post an issue to the original package (@theuiteam/continuous-container) to support the "exports" field. If that is not possible, create a JSPM override to customize the exports field for this package.

Readme

🧒 - 👨‍🦱 - 👨‍🦳

Continuous Container


Something with known past, present, and the future
a `useState` aware of continuous nature of time

Idea

This is almost react transition group, but for state management...

Why people react transition group? Because it 1) takes a pause between steps letting classNames be applied and 2) keeps children after you remove them, to perform a fade animation.

We are doing the same, but using state.

It's all about tracking what the value would be, what is right now, and what it was.

  • future - the next value. The value you just set.
  • present - to be synchronized with the future "later"
  • past - to be synchronized with the present "later"

and

  • defined - an indication that any of future, past or preset are truthy.

API

useContinuousState

const co

Usage

Problem statement

Let's imagine you have a switch. Which controls visibility of something, but you also want to add some animation.

Let's handle these cases separately:

const App = () => {
    const [on, setOn] = useState(false);

    return (
        <div>
            <button onClick={() => setOn(on => !on)}>Toggle</button>
            // would be instanly hidden and shown
            {on && <Content/>}
            // would be animated, but would be ALWAYS rendered
            <ContentWithAnimation visible={on}/>}
        </div>
    );
};

Now let's imagine you want to not render Content when it's not visible and not required.

Ok, "when is this when"?

  • render ContentWithAnimation when it is about to be displayed
  • render ContentWithAnimation when it is displayed
  • render ContentWithAnimation when it is no longer visible, but still animating toward hidden state
import {ContinuousContainer, useContinuousState} from '@theuiteam/continuous-container';

const App = () => {
    const [on, setOn] = useState(false);
    const continuousState = useContinuousState(on);

    return (
        <div>
            <button onClick={() => setOn(on => !on)}>Toggle</button>
            {/*render if any of past/preset/future is set to true*/}
            {continuousState.defined && (
                <ContentWithAnimation visible={continuousState.present}/>
                // wire the "present" state
            )}
            {/* or */}
            <ContinuousContainer value={on} timeout={300}>
                {(past, present, future) =>
                    (past || present || future) &&
                    <ContentWithAnimation visible={present}/>
                    // ^^ use the "present" value
                }
            </ContinuousContainer>
        </div>
    )
}

Scattered

There are more sophisticated situations, when setting up something to display does not mean "display". Lazy loading is a good case

const App = () => {
    const continuousState = useContinuousState(on);
    return continuousState.defined && (
        <LazyLoadedContentWithAnimation visible={continuousState.present}/>
    )
}

In such case ContinuousState will update from future to present before LazyLoadedContentWithAnimation component is loaded, breaking a connection between states.

In order to handle this problem one might need to tap into rendering process using useScatteredContinuousState

    const continuousState = useScatteredContinuousState(on);
return continuousState.defined && (
    <Suspense>
        <LazyLoadedContentWithAnimation visible={continuousState.present}>
            <continuousState.DefinePresent/>
            {/*this component will advance ContinuousState once rendered*/}
        </LazyLoadedContentWithAnimation>
    </Suspense>
)

For readability purposes we recommend putting DefinePresent to a separate slot different from children.

<LazyLoadedContentWithAnimation visible={continuousState.present} effector={<continuousState.DefinePresent/>}/>

See also

  • Phased Container from a recondition library

License

MIT