Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[next.js] global plugins do not register before logic components #60

Closed
amrdraz opened this issue Oct 26, 2017 · 9 comments
Closed

[next.js] global plugins do not register before logic components #60

amrdraz opened this issue Oct 26, 2017 · 9 comments

Comments

@amrdraz
Copy link
Contributor

amrdraz commented Oct 26, 2017

Hello there,

so, after quite a bit of debugging I noticed that including plugins directly works

// components/Users.js
...
import thunkPlugin from  "kea-thunk";
import { kea } from "kea";

export default  kea({
  plugins: [thunkPlugin],
  path: () => ["kea", "Users"],
  thunks: ({ actions }) =>  {
  ...
})(function Users(props)=>{...})

however registering plugins on the store level does not

// store.js
import thunkPlugin from 'kea-thunk'
import { getStore } from "kea";

export const createStore = preloadedState => getStore({ plugins: [thunkPlugin] })

upon inspection I noticed that the kea function is executed before the ActivatePlugins function is.

This happens even if I call the store before importing the component for some reason 🤔

// pages/index.js
import React, {Component} from 'react'
import { Provider } from 'react-redux'
import { createStore } from '../store'
let store = createStore()

import Users from '../components/Users'

export default class LandingPage extends Component {
  render() {
    return <Provider store={store}>
      <Users/>
    </Provider>
  }
}

And once the logic is initialized the global plugin is never referred to later
in this case all actions declared in thunks never show up.

so far I resolved this by simply directly including the plugin

any idea why?

my current proposed solutions are make global plugins run on already initialized logic
allways use plugins on the logic level (which I will do until a solution is presented)

in the mean time

I only figured out I can use plugins on the logic level by following by inspecting the code
would be nice if this is mentioned in the thunk plugin documentation
I realized later it's already mentioned in the kea function documentation but it's kinda not where I would have looked when faced with a problem related to a plugin

thank you for you time 😃

@ghost ghost mentioned this issue Oct 27, 2017
@mariusandra
Copy link
Member

Hey, first, I'm not sure this is possible:

import { createStore } from '../store'
let store = createStore()

import Users from '../components/Users'

ES requires that all imports be defined at the top of the file. So it's possible that in your transpiled code, the let is moved around.

You may try to just use this to install the plugin without going through the store:

import 'kea-thunk/install'

of course running it before any call to kea({}) takes place, or running activatePlugin(thunkPlugin) directly like described here: https://github.com/keajs/kea-thunk

This global vs local plugins thing is very recent, and while it works great in my own app (and kea-website), there might be some cases that I could have missed. The entire plugin system is still a bit of work in progress, although I don't expect it to change much. So thank you for reporting and I hope you can get it working.

@mariusandra
Copy link
Member

Few more points:

  1. I upgraded the documentation on https://kea.js.org/ to include all the installation methods for the three plugins present (saga, thunk, localstorage).

  2. You should only install the thunk plugin globally, as it needs to add its middleware to the store. In the latest versions of kea and kea-thunk, it will complain if you try to use it locally.

  3. Please upgrade to the latest versions and try again :)

@amrdraz
Copy link
Contributor Author

amrdraz commented Oct 27, 2017

so this update basically made me switch from adding the thunk plugin to every module containing kea logic, to importing kea-thunk/install in every module (so that one of them may run first)

Just adding the plugin globally in my store.js file doesn't work since when server rendering with next.js the store is created with the page component, which will always happen after imports

I tried to import the store first and in the module create a store with the plugin but that didn't work ( though I didn't make sure why)

At first I was not happy about the misdirection and having to call install/thunk on every module, even though it's less code than adding the plugin to the component, it felt less explicit (someone reading the code has to know what install does) which is bad DX (developer experience) in my opinion.

but then I guess it is better in the it makes it known that a plugin is enabling the thunk feature

@amrdraz
Copy link
Contributor Author

amrdraz commented Oct 27, 2017

I think we can close this issue for now

@mariusandra
Copy link
Member

Hey, I'm not sure how next.js does its magic, nor have I had time to play with it.

But, logically... it should be possible to get it to work somehow. Perhaps injecting them to the webpack config's entry point?

@mariusandra mariusandra changed the title global plugins do not register before logic components [next.js] global plugins do not register before logic components Oct 27, 2017
@amrdraz
Copy link
Contributor Author

amrdraz commented Oct 27, 2017

I'm satisfied with the current solution so I won't invest more in figuring it out

next.js is not magical, the next-redux-wrapper package is the culprit here but it does what it does for server side rendering and code splitting to work well by setting up the store properly.

I could probably reach a recommendation after sometime (though I don't think it will include messing with the webpack configurations), as stated the current system works will for me

when it becomes an issue it will be addressed

@mariusandra
Copy link
Member

Ok, closing the issue then. When you or anyone else has more to add, feel free to reopen.

@wuzhuzhu
Copy link

wuzhuzhu commented Apr 9, 2018

@amrdraz 's way works fine.
But I encountered this issue in a create-react-app application. Is there any fix plan ?

@ghost
Copy link

ghost commented Apr 2, 2019

I'm currently trying to integrate kea & the kea-saga plugin into my next.js project. I've been using the next-redux-wrapper and the next-redux-saga modules in order the configure the application store using this configuration:

store.js

const reducers = combineReducers({
  kea: keaReducer('kea'),
  concepts: keaReducer('concepts'),
})

const bindMiddleware = middleware => {
  if (process.env.NODE_ENV !== 'production') {
    const { composeWithDevTools } = require('redux-devtools-extension')
    return composeWithDevTools(applyMiddleware(...middleware))
  }
  return applyMiddleware(...middleware)
}

const configureStore = (preloadedState = {}) => {
  /**
   * Activate Kea plugins with every context
   */

  activatePlugin(sagaPlugin)

  /**
   * Recreate the stdChannel (saga middleware) with every context.
   */

  const sagaMiddleware = createSagaMiddleware()

  /**
   * Since Next.js does server-side rendering, you are REQUIRED to pass
   * `preloadedState` when creating the store.
   */

  const store = createStore(reducers, preloadedState, bindMiddleware([sagaMiddleware]))

  /**
   * next-redux-saga depends on `sagaTask` being attached to the store.
   * It is used to await the rootSaga task before sending results to the client.
   */

  store.sagaTask = sagaMiddleware.run(keaSaga)

  return store
}

When requesting any page, the app is just hanging there.`

@amrdraz or @mariusandra could you reopen the issue. I can also help in making this work if you just point me in the right direction. It's a critical feature for us, as we need SSR.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants