@xstate/react
Advanced tools
Comparing version 1.0.0-rc.3 to 1.0.0-rc.4
import { StateMachine, EventObject, Typestate } from '@xstate/fsm'; | ||
export declare function useMachine<TC extends object, TE extends EventObject = EventObject>(stateMachine: StateMachine.Machine<TC, TE, any>, options?: { | ||
actions?: StateMachine.ActionMap<TC, TE>; | ||
}): [StateMachine.State<TC, TE, any>, StateMachine.Service<TC, TE>['send'], StateMachine.Service<TC, TE>]; | ||
export declare function useMachine<TContext extends object, TEvent extends EventObject = EventObject, TState extends Typestate<TContext> = any>(stateMachine: StateMachine.Machine<TContext, TEvent, TState>, options?: { | ||
actions?: StateMachine.ActionMap<TContext, TEvent>; | ||
}): [StateMachine.State<TContext, TEvent, TState>, StateMachine.Service<TContext, TEvent>['send'], StateMachine.Service<TContext, TEvent>]; | ||
export declare function useService<TContext extends object, TEvent extends EventObject = EventObject, TState extends Typestate<TContext> = any>(service: StateMachine.Service<TContext, TEvent, TState>): [StateMachine.State<TContext, TEvent, TState>, StateMachine.Service<TContext, TEvent, TState>['send'], StateMachine.Service<TContext, TEvent, TState>]; | ||
//# sourceMappingURL=fsm.d.ts.map |
@@ -1,16 +0,4 @@ | ||
import { EventObject, StateMachine, State, Interpreter, InterpreterOptions, MachineOptions, StateConfig, Typestate } from 'xstate'; | ||
interface UseMachineOptions<TContext, TEvent extends EventObject> { | ||
/** | ||
* If provided, will be merged with machine's `context`. | ||
*/ | ||
context?: Partial<TContext>; | ||
/** | ||
* The state to rehydrate the machine to. The machine will | ||
* start at this state instead of its `initialState`. | ||
*/ | ||
state?: StateConfig<TContext, TEvent>; | ||
} | ||
export declare function useMachine<TContext, TEvent extends EventObject, TTypestate extends Typestate<TContext> = any>(machine: StateMachine<TContext, any, TEvent, TTypestate>, options?: Partial<InterpreterOptions> & Partial<UseMachineOptions<TContext, TEvent>> & Partial<MachineOptions<TContext, TEvent>>): [State<TContext, TEvent, any, TTypestate>, Interpreter<TContext, any, TEvent, TTypestate>['send'], Interpreter<TContext, any, TEvent, TTypestate>]; | ||
export declare function useService<TContext, TEvent extends EventObject, TTypestate extends Typestate<TContext> = any>(service: Interpreter<TContext, any, TEvent, TTypestate>): [State<TContext, TEvent, any, TTypestate>, Interpreter<TContext, any, TEvent, TTypestate>['send'], Interpreter<TContext, any, TEvent, TTypestate>]; | ||
export {}; | ||
export { useService } from './useService'; | ||
export { useMachine } from './useMachine'; | ||
export { useActor } from './useActor'; | ||
//# sourceMappingURL=index.d.ts.map |
111
lib/index.js
"use strict"; | ||
var __assign = (this && this.__assign) || function () { | ||
__assign = Object.assign || function(t) { | ||
for (var s, i = 1, n = arguments.length; i < n; i++) { | ||
s = arguments[i]; | ||
for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p)) | ||
t[p] = s[p]; | ||
} | ||
return t; | ||
}; | ||
return __assign.apply(this, arguments); | ||
}; | ||
var __rest = (this && this.__rest) || function (s, e) { | ||
var t = {}; | ||
for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p) && e.indexOf(p) < 0) | ||
t[p] = s[p]; | ||
if (s != null && typeof Object.getOwnPropertySymbols === "function") | ||
for (var i = 0, p = Object.getOwnPropertySymbols(s); i < p.length; i++) { | ||
if (e.indexOf(p[i]) < 0 && Object.prototype.propertyIsEnumerable.call(s, p[i])) | ||
t[p[i]] = s[p[i]]; | ||
} | ||
return t; | ||
}; | ||
var __read = (this && this.__read) || function (o, n) { | ||
var m = typeof Symbol === "function" && o[Symbol.iterator]; | ||
if (!m) return o; | ||
var i = m.call(o), r, ar = [], e; | ||
try { | ||
while ((n === void 0 || n-- > 0) && !(r = i.next()).done) ar.push(r.value); | ||
} | ||
catch (error) { e = { error: error }; } | ||
finally { | ||
try { | ||
if (r && !r.done && (m = i["return"])) m.call(i); | ||
} | ||
finally { if (e) throw e.error; } | ||
} | ||
return ar; | ||
}; | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
var react_1 = require("react"); | ||
var xstate_1 = require("xstate"); | ||
var use_subscription_1 = require("use-subscription"); | ||
var useConstant_1 = require("./useConstant"); | ||
function useMachine(machine, options) { | ||
if (options === void 0) { options = {}; } | ||
if (process.env.NODE_ENV !== 'production') { | ||
var _a = __read(react_1.useState(machine), 1), initialMachine = _a[0]; | ||
if (machine !== initialMachine) { | ||
console.warn('Machine given to `useMachine` has changed between renders. This is not supported and might lead to unexpected results.\n' + | ||
'Please make sure that you pass the same Machine as argument each time.'); | ||
} | ||
} | ||
var context = options.context, guards = options.guards, actions = options.actions, activities = options.activities, services = options.services, delays = options.delays, rehydratedState = options.state, interpreterOptions = __rest(options, ["context", "guards", "actions", "activities", "services", "delays", "state"]); | ||
var service = useConstant_1.default(function () { | ||
var machineConfig = { | ||
context: context, | ||
guards: guards, | ||
actions: actions, | ||
activities: activities, | ||
services: services, | ||
delays: delays | ||
}; | ||
var createdMachine = machine.withConfig(machineConfig, __assign(__assign({}, machine.context), context)); | ||
return xstate_1.interpret(createdMachine, interpreterOptions).start(rehydratedState ? xstate_1.State.create(rehydratedState) : undefined); | ||
}); | ||
var _b = __read(react_1.useState(service.state), 2), state = _b[0], setState = _b[1]; | ||
react_1.useEffect(function () { | ||
service.onTransition(function (currentState) { | ||
if (currentState.changed) { | ||
setState(currentState); | ||
} | ||
}); | ||
// if service.state has not changed React should just bail out from this update | ||
setState(service.state); | ||
return function () { | ||
service.stop(); | ||
}; | ||
}, []); | ||
// Make sure actions and services are kept updated when they change. | ||
// This mutation assignment is safe because the service instance is only used | ||
// in one place -- this hook's caller. | ||
react_1.useEffect(function () { | ||
Object.assign(service.machine.options.actions, actions); | ||
}, [actions]); | ||
react_1.useEffect(function () { | ||
Object.assign(service.machine.options.services, services); | ||
}, [services]); | ||
return [state, service.send, service]; | ||
} | ||
exports.useMachine = useMachine; | ||
function useService(service) { | ||
var subscription = react_1.useMemo(function () { return ({ | ||
getCurrentValue: function () { return service.state || service.initialState; }, | ||
subscribe: function (callback) { | ||
var unsubscribe = service.subscribe(function (state) { | ||
if (state.changed !== false) { | ||
callback(); | ||
} | ||
}).unsubscribe; | ||
return unsubscribe; | ||
} | ||
}); }, [service]); | ||
var state = use_subscription_1.useSubscription(subscription); | ||
return [state, service.send, service]; | ||
} | ||
exports.useService = useService; | ||
var useService_1 = require("./useService"); | ||
exports.useService = useService_1.useService; | ||
var useMachine_1 = require("./useMachine"); | ||
exports.useMachine = useMachine_1.useMachine; | ||
var useActor_1 = require("./useActor"); | ||
exports.useActor = useActor_1.useActor; |
{ | ||
"name": "@xstate/react", | ||
"version": "1.0.0-rc.3", | ||
"version": "1.0.0-rc.4", | ||
"description": "XState tools for React", | ||
@@ -37,3 +37,4 @@ "keywords": [ | ||
"test": "jest", | ||
"prepublish": "npm run build && npm run test" | ||
"prepublish": "npm run build && npm run test", | ||
"prerelease": "npm publish --tag next" | ||
}, | ||
@@ -57,3 +58,3 @@ "bugs": { | ||
"dependencies": { | ||
"use-subscription": "^1.3.0" | ||
"use-subscription": "^1.4.0" | ||
}, | ||
@@ -73,5 +74,5 @@ "devDependencies": { | ||
"ts-jest": "^24.1.9", | ||
"typescript": "^3.7.2", | ||
"typescript": "^3.8.3", | ||
"xstate": "*" | ||
} | ||
} |
@@ -234,4 +234,6 @@ # @xstate/react | ||
Using a `switch` statement might suffice for a simple, non-hierarchical state machine, but for [hierarchical](https://xstate.js.org/docs/guides/hierarchical.html) and [parallel](https://xstate.js.org/docs/guides/parallel.html) machines, the state values will be objects, not strings. In this case, it's better to use [`state.matches(...)`](https://xstate.js.org/docs/guides/states.html#state-methods-and-getters): | ||
When using [hierarchical](https://xstate.js.org/docs/guides/hierarchical.html) and [parallel](https://xstate.js.org/docs/guides/parallel.html) machines, the state values will be objects, not strings. In this case, it is best to use [`state.matches(...)`](https://xstate.js.org/docs/guides/states.html#state-methods-and-getters). | ||
We can do this with `if/else if/else` blocks: | ||
```js | ||
@@ -250,2 +252,17 @@ // ... | ||
We can also continue to use `switch`, but we must make an adjustment to our approach. By setting the expression of the `switch` to `true`, we can use [`state.matches(...)`](https://xstate.js.org/docs/guides/states.html#state-methods-and-getters) as a predicate in each `case`: | ||
```js | ||
switch (true) { | ||
case current.matches('idle'): | ||
return /* ... */; | ||
case current.matches({ loading: 'user' }): | ||
return /* ... */; | ||
case current.matches({ loading: 'friends' }): | ||
return /* ... */; | ||
default: | ||
return null; | ||
} | ||
``` | ||
A ternary statement can also be considered, especially within rendered JSX: | ||
@@ -252,0 +269,0 @@ |
Major refactor
Supply chain riskPackage has recently undergone a major refactor. It may be unstable or indicate significant internal changes. Use caution when updating to versions that include significant changes.
Found 1 instance in 1 package
27597
17
382
334
1
Updateduse-subscription@^1.4.0