Skip to content

Instantly share code, notes, and snippets.

@yarigpopov
Last active October 15, 2021 22:52
Show Gist options
  • Save yarigpopov/eecbbe53618c2b4304b69fa08a195f82 to your computer and use it in GitHub Desktop.
Save yarigpopov/eecbbe53618c2b4304b69fa08a195f82 to your computer and use it in GitHub Desktop.
import React from "react";
import async from "./async-machine";
import { interpret } from "xstate";
function noop() {}
// create a Provider/Consumer pair
const AsyncContext = React.createContext({});
AsyncContext.displayName = "Async";
class Async extends React.Component {
static Consumer = AsyncContext.Consumer;
constructor() {
super(...arguments);
const { trigger, onSuccess, onError } = this.props;
// start a xstate-service and setup `this.state`
const service = interpret(
async.withContext({
trigger: trigger || noop,
onSuccess: onSuccess || noop,
onError: onError || noop
})
);
this.state = {
service,
current: service.initialState,
send: service.send,
trigger: service.send.bind(null, { type: "DO" }),
isIdle: true,
didError: false,
didSucceed: false,
isBusy: false
};
// update `this.state` when service transitions to new state
service.onTransition((current) => {
this.setState({
current,
didError: current.matches("error"),
isIdle: current.matches("idle"),
didSucceed: current.matches("success"),
isBusy: current.matches("busy")
});
});
}
// use lifecycle hooks to start/stop service
componentDidMount() {
this.state.service.start();
}
componentWillUnmount() {
this.state.service.stop();
}
render() {
const { children } = this.props;
return (
<div>
<AsyncContext.Provider value={this.state}>
{children}
</AsyncContext.Provider>
</div>
);
}
}
export default Async;
import React from 'react';
import Async from './Async';
import asyncThing from './async-thing';
export default function App() {
return (
<div className="App">
<Async trigger={asyncThing}>
<h1>React - Async Provider</h1>
<Async.Consumer>
{({ current, isBusy, trigger }) => (
<div>
<div>{current.value}</div>
<button type="button" disabled={isBusy} onClick={trigger}>
click
</button>
</div>
)}
</Async.Consumer>
</Async>
</div>
);
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment