question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

Access context inside effect

See original GitHub issue

Hey! 👋🏽

I’m trying out this library and I’m wondering about accessing the context within an effect.

My question regards something like this:

  1. Effect on initial state updates context and transits to another state
  2. Effect on the next state uses data set by the previous effect <- this is the part I’m asking about
Example
import useStateMachine from '@cassiozen/usestatemachine';

const [state, send] = useStateMachine({ count: 0 })({
  initial: 'first',
  states: {
    first: {
      on: { second: 'second' },
      effect(send, update) {
        update(context => ({ count: context.count + 1 }));
        send('second');
      },
    },
    second: {
      effect(send, update) { // <- context isn't accessible here
        console.log(state.context.count); // is this the only/correct way to access it?
      },
    },
  },
});

Being recently new to state machines, I’m wondering if this is by design and/or if context could be a parameter to the effect function. If could be added, I’d love to contribute to it!

I have used xstate a bit and there I can access context within actions and services. useEffectReducer allows access to context within effects.

Issue Analytics

  • State:closed
  • Created 2 years ago
  • Comments:13 (11 by maintainers)

github_iconTop GitHub Comments

1reaction
cassiozencommented, Jul 12, 2021

This was a good catch, @gchallen - and it seems to be related to the way React works. Since this is built on top of useReducer and useEffect, when a transition happens, it will forcefully run the exit effect followed by the entry effect. If the exit callback does anything that causes a state change, it will be scheduled to happen after the entry callback.

I will investigate any possible solutions for this, but it might not be simple.

1reaction
gchallencommented, Jul 1, 2021

I’m seeing some confusing behavior that I think is related to this change. Specifically, if I return a completion method from an effect that uses setContext, any changes made are not visible to the entry function for the next state:

// Trimmed down example that may or may not actually work, but hopefully makes the point
const [state, send] = useStateMachine<{ test?: boolean }>()({
    initial: "recording",
    states: {
      recording: {
        on: { STOP: "replaying" },
        effect({ context, setContext }) {
          return () => {
            setContext(() => ({ test: true }))
          }
        },
      },
      replaying: {
        on: { RECORD: "recording" },
        effect({ context }) {
          console.log(context?.test!) // prints undefined
        },
      },
    },
  })

I’d expect the finalizer for the recording state to run before the entry method for the replaying state, and any changes that it makes to the context object to be visible.

I can probably refactor my code to work around this, but it may be worth a note in the documentation. In my case the reason to do it this way is that the recording method returns a stop handle which has to be used to stop the recording, and it’s easier to do that within the same method rather than storing that handle somewhere so it’s visible in the entry method for the replaying state.

Read more comments on GitHub >

github_iconTop Results From Across the Web

Accessing context from useEffect - reactjs - Stack Overflow
When I attempt to access it inside useEffect I get a the react-hooks/exhaustive-deps ESLint message. For example the following code, although it ...
Read more >
How to use React Context like a pro - Devtrium
First, we'll create a UserContextProvider component inside of a new file called UserContext.jsx . ... );. };. const Page = () => {...
Read more >
A Guide to React Context and useContext() Hook
The main idea of using the context is to allow your components to access some global data and re-render when that global data...
Read more >
How to Use Context API with Hooks While Avoiding Bottlenecks
We can make it a bit less tedious by using a wrapper for the useContext hook call. Head to the GlobalSpinnerContext.
Read more >
React.js — Basic Hooks (useState, useEffect, & useContext)
A Context object is created via the createContext() function in React. js (line 3 in the first photo). This object always comes with...
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found