xstate
xstate copied to clipboard
v5 - Bug: Context from machine.withContext() is ignored for React's useMachine
Description
When using useMachine from a machine where withContext has been used, the resulting machine's state will have the original machine's context.
Example from reproduction's link:
// Where machine's context is { count: 0 }
const [state] = useMachine(toggleMachine.withContext({ count: 5 }));
Just started experimenting with V5. Please tell me if I should report other issues I may find (or contribute to fix).
Expected result
{ count: 5 }
Actual result
{ count: 0 }
Reproduction
https://codesandbox.io/s/dreamy-rubin-17lmfv?file=/src/index.js
Additional context
Versions
xstate: 5.0.0-alpha.0 @xstate/react: 4.0.0-alpha.0
Thanks for testing out our newest alpha releases! It's really appreciated.
I already see what's wrong - gonna prepare a PR soon for this problem.
Actually... I could fix this particular issue somewhat quickly but this has shown me that how context values are "merged" is actually kinda complicated right now. So I think I will take this as an opportunity to rethink this and maybe simplify it if possible. This input RFC has also the potential for substantially changing the code here so I think it makes sense to think about fixing this problem when we decide what to do about input
The .withContext({ ... }) method is removed. Using input (xstate@beta) is now the recommended way of doing this:
import "./styles.css";
import React from "react";
import ReactDOM from "react-dom";
import { createMachine } from "xstate";
import { useMachine } from "@xstate/react";
const toggleMachine = createMachine({
id: "toggle",
context: ({ input }) => ({
count: input?.count ?? 0
})
});
function App() {
const [withInputState] = useMachine(toggleMachine, {
input: { count: 5 }
});
return (
<div className="App">
<h1>Initial State's context</h1>
<pre>{JSON.stringify(toggleMachine.initialState.context)}</pre>
<h1>Context when using input</h1>
<pre>{JSON.stringify(withInputState.context)}</pre>
</div>
);
}
const rootElement = document.getElementById("root");
ReactDOM.render(<App />, rootElement);
https://codesandbox.io/s/damp-sun-wxh
fys?file=/src/index.js:0-749