Easy-peasy: Using Easy Peasy in Gatsby

Created on 14 Oct 2019  路  9Comments  路  Source: ctrlplusb/easy-peasy

Hello, im getting this error, im using gatsby 2.15.36 with a fresh new install using gatsby new command

Uncaught Error: An error occurred trying to map state in a useStoreState hook: Cannot read property 'getState' of undefined. at useStoreState (easy-peasy.esm.js:41)

question

Most helpful comment

I have a working setup with TypeScript which works well:

// src/store/models/counter.ts

import { action, Action, thunk, Thunk } from 'easy-peasy';

interface Counter {
  count: number,
  setCount: Action<Counter, number>
  asyncSetCount: Thunk<Counter, number>
}

const counter: Counter = {
  count: 0,

  setCount: action((state, payload) => {
    state.count = payload;
  }),

  asyncSetCount: thunk(async (actions, payload) => {
    await actions.setCount(payload);
  }),
};

export default counter;
// src/store/index.ts

import { createStore, createTypedHooks } from 'easy-peasy';
import counter from './models/counter';

export const models = {
  counter,
};

export const {
  useStore,
  useStoreState,
  useStoreActions,
  useStoreDispatch,
} = createTypedHooks<typeof models>();

export default createStore(models);
// wrapWithProvider.js

import React from 'react';
import PropTypes from 'prop-types';
import { StoreProvider } from 'easy-peasy';
import store from './src/store';

const wrapWithProvider = ({ element }) => (
  <StoreProvider store={store}>
    {element}
  </StoreProvider>
);

wrapWithProvider.propTypes = {
  element: PropTypes.node.isRequired,
};

export default wrapWithProvider;
// gatsby-ssr.js
// gatsby-browser.js

import wrapWithProvider from './wrapWithProvider';

export const wrapRootElement = wrapWithProvider;

All 9 comments

also i've used this example to create my store

Hey @wrtisans

Is your app correctly wrapped with the StoreProvider?

as i say, i've followed the same steps as the guide, here are my main layout

import React from 'react'
import PropTypes from 'prop-types'
import { StoreProvider } from 'easy-peasy'

import '../assets/styles/main.css'
import store from '../store/store'

const MainLayout = ({ children }) => (
        <StoreProvider store={store}>
                <main>{children}</main>
        </StoreProvider>
)

MainLayout.propTypes = {
        children: PropTypes.node.isRequired,
}

export default MainLayout`

store.js
`import { createStore, action } from 'easy-peasy'

const store = createStore({
        todos: {
                items: ['Create store', 'Wrap application', 'Use store'],
                add: action((state, payload) => {
                        state.items.push(payload)
                }),
        },
})

export default store
`
login.js
`
export default function LoginPage({ data }) {
        const todos = useStoreState(state => state.todos.items)
        const classes = useStyles()
 <MainLayout>
                        <Grid container component="main" className={classes.root}>
                               {...otherStuff}
                        </Grid>
 </MainLayout>

If you look closely your LoginPage is accessing the store, however, the store is only getting exposed via its children, within the MainLayout.

I am away from keyboard right now, but I can later show one technique to resolve this.

Yes please, thanks a lot!

Hey @wrtisans

I have yet to use Gatsby myself, but in terms of configuring the StoreProvider you would need to follow a similar strategy as if you were implementing a standard react-redux Provider. The Gatsby repo has an example you can reference:

https://github.com/gatsbyjs/gatsby/tree/master/examples/using-redux

Would be great to create an official example for Gatsby. Right now I am with my newly born twins so don't have the time. 馃榾

Would be great to create an official example for Gatsby. Right now I am with my newly born twins so don't have the time. 馃榾

Congrats!!

I have a working setup with TypeScript which works well:

// src/store/models/counter.ts

import { action, Action, thunk, Thunk } from 'easy-peasy';

interface Counter {
  count: number,
  setCount: Action<Counter, number>
  asyncSetCount: Thunk<Counter, number>
}

const counter: Counter = {
  count: 0,

  setCount: action((state, payload) => {
    state.count = payload;
  }),

  asyncSetCount: thunk(async (actions, payload) => {
    await actions.setCount(payload);
  }),
};

export default counter;
// src/store/index.ts

import { createStore, createTypedHooks } from 'easy-peasy';
import counter from './models/counter';

export const models = {
  counter,
};

export const {
  useStore,
  useStoreState,
  useStoreActions,
  useStoreDispatch,
} = createTypedHooks<typeof models>();

export default createStore(models);
// wrapWithProvider.js

import React from 'react';
import PropTypes from 'prop-types';
import { StoreProvider } from 'easy-peasy';
import store from './src/store';

const wrapWithProvider = ({ element }) => (
  <StoreProvider store={store}>
    {element}
  </StoreProvider>
);

wrapWithProvider.propTypes = {
  element: PropTypes.node.isRequired,
};

export default wrapWithProvider;
// gatsby-ssr.js
// gatsby-browser.js

import wrapWithProvider from './wrapWithProvider';

export const wrapRootElement = wrapWithProvider;
Was this page helpful?
0 / 5 - 0 ratings

Related issues

ifyoumakeit picture ifyoumakeit  路  5Comments

johnnythunder picture johnnythunder  路  6Comments

gino8080 picture gino8080  路  5Comments

djgrant picture djgrant  路  6Comments

24dev picture 24dev  路  5Comments