Skip to content

Instantly share code, notes, and snippets.

@muneneevans
Last active June 20, 2020 09:36
Show Gist options
  • Save muneneevans/3ffb7eaf027fdd005d6dc93a3469f2cd to your computer and use it in GitHub Desktop.
Save muneneevans/3ffb7eaf027fdd005d6dc93a3469f2cd to your computer and use it in GitHub Desktop.
Xstate
import React, { Component } from "react";
import { Machine, assign } from "xstate";
import { useMachine } from "@xstate/react";
const allData = new Array(25).fill(0).map((_val, i) => i + 1);
const perPage = 10;
const dataMachine = new Machine({
id: "dataMachine",
initial: "loading",
context: {
data: [],
},
states: {
loading: {
invoke: {
id: "dataLoader",
src: (context, event) => {
return (callback, onEvent) => {
setTimeout(() => {
const { data } = context;
const newData = allData.slice(data.length, data.length + perPage);
const hasMore = newData.length === perPage;
if (hasMore) {
callback({ type: "DONE_MORE", newData });
} else {
callback({ type: "DONE_COMPLETE", newData });
}
}, 2000);
};
},
},
on: {
DONE_MORE: {
target: "more",
actions: assign({
data: ({ data }, { newData = [] }) => [...data, ...newData],
}),
},
DONE_COMPLETE: {
target: "complete",
actions: assign({
data: ({ data }, { newData = [] }) => [...data, ...newData],
}),
},
FAIL: "failure",
},
},
more: {
on: {
LOAD: "loading",
},
},
complete: {
type: "final",
},
failure: {
type: "final",
},
},
});
const App = ({}) => {
const [current, send] = useMachine(dataMachine);
const { data } = current.context;
return (
<div className="App">
<ul>
{data.map((row) => (
<li key={row} style={{ background: "orange" }}>
{row}
</li>
))}
{current.matches("loading") && <li>Loading...</li>}
{current.matches("more") && (
<li style={{ background: "green" }}>
<button
onClick={() => {
send("LOAD");
}}
>
Load More
</button>
</li>
)}
</ul>
</div>
);
};
export default App;
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment