Bug?
export function Todo({ todoRef }) {
const [state, send] = useService(todoRef);
...
On the TodoMVC example, we can call useService and pass an actor ( todoRef) , but with Typescript Argument of type 'Actor<...>' is not assignable to parameter of type 'Interpreter<...>'.
I searched in the comments and saw a typescript implementation of todoMVC, but it ditched the whole conflict and work around the problem, using useMachine(Machine) instead of useService(Actor)
I would like to use useService(Actor) in ts
Argument of type 'Actor<...>' is not assignable to parameter of type 'Interpreter<...>'.
Sorry I honestly do not know how to solve it, but if there's anything i could help let me know 馃憤
I'm using this workaround for now:
const [refState, sendToRef] = useService(machine.context.ref! as unknown as Interpreter<RefContext, RefSchema, RefEvent>)
Hi @edgarjrg
The example you gave, I manage to make it work as follow:
interface Todo {
id: number;
title: string;
completed: boolean;
}
export function Todo({ todoRef }) {
const [state, send] = useService<Todo, EventObject>(todoRef);
const inputRef = useRef(null);
const { id, title, completed } = state.context;
It was that you wanted to achieve? But truth to be told if you don't type the TContext in the useService you will get an error in this line:
const { id, title, completed } = state.context;
So I wonder if we wouldn't want to change in the package to:
export function useService<TContext = any, TEvent extends EventObject = EventObject>(
service: Interpreter<TContext, any, TEvent>
):
@davidkpiano Does it makes sense?
@assuncaocharles any doesn't give you any type safety - so, in general, providing implicit anys in library typings is discouraged
The problem here seems different - spawned machine needs to return Interpreter's instance (which extends Actor interface) instead of bare Actor. Gonna try to fix this in a moment.
@Andarist Alright, so I got it wrong. Not sure where to look then, will wait you PR to see and get more familiar with the codebase :)
Before we do that, we should probably consider a useActor() hook for all types of actors, not just services. That would resolve this.
@davidkpiano for curiosity what would differentiate useActor from useService ? just the typings or is anything inherently different ?
I agree with @Andarist , it's a bit strange to have an Actor instance at spawn, but maybe it's more semantic to useActor if the semantic difference is worth it.
@davidkpiano I believe @edgarjrg's intention was to use spawned machine in the very same way as "top level" service, using the same API and all. Potential useActor hook wouldn't provide that as actors (at least for now) don't have a notion of their state which is first thing returned from useService hook
What is the way to use a actor in a service in the 4.7 (rc 5) version?
import * as React from "react";
import { useActor } from "@xstate/react";
import { ProductOptionStepType } from "../../../Types/Types";
interface IFormatProps {
option: ProductOptionStepType;
}
const Format: React.FC<IFormatProps> = ({ option }) => {
const [current, send] = useActor(option.ref);
}
This does not work.
const [current, send] = useService(option.ref! as unknown as Interpreter<any, any, any>);
This does not work either (worked in 4.6.x).
@DirkWolthuis Can you open this in a separate issue?
Done #772
Most helpful comment
@davidkpiano I believe @edgarjrg's intention was to use spawned machine in the very same way as "top level" service, using the same API and all. Potential
useActorhook wouldn't provide that as actors (at least for now) don't have a notion of their state which is first thing returned fromuseServicehook