webext-redux icon indicating copy to clipboard operation
webext-redux copied to clipboard

Make Aliases Easy by Following electron-redux's Lead?

Open vhmth opened this issue 6 years ago • 4 comments

https://www.useloom.com/share/d3e482bbc3354bd0b1c1b6fadb5f8fd6

https://github.com/tshaddix/react-chrome-redux/pull/131#issuecomment-381700100

vhmth avatar Apr 20 '18 00:04 vhmth

@vhmth Agreed - this is a great idea!

I'm wondering what the best implementation structure would look like. Ideally we want this to be configured into a store so that we continue to same composability paradigm we've been using before (you can have multiple proxy or background stores without any complication).

Creating the alias action is easy, and the storage is easy (we can just store internally exactly how we are now). The question is how we attach to a store.

The middleware was nice because it was transparent in what it was doing and just used redux's store api.

I can see us doing it through the wrapStore call or the middleware method, potentially...

tshaddix avatar Apr 20 '18 15:04 tshaddix

So the middleware way being turning something like this:

// background.js

import { applyMiddleware, createStore } from 'redux';
import { alias, wrapStore } from 'react-chrome-redux';

const aliases = {
  // this key is the name of the action to proxy, the value is the action
  // creator that gets executed when the proxied action is received in the
  // background
  'user-clicked-alias': () => {
    // this call can only be made in the background script
    chrome.notifications.create(...);

  };
};

const store = createStore(rootReducer,
  applyMiddleware(
    alias(aliases)
  )
);

Into something like this:

// background.js

import { applyMiddleware, createStore } from 'redux';
import { aliases, wrapStore } from 'react-chrome-redux';

aliases.createAlias("user-clicked-alias", () => {
  // this call can only be made in the background script
  chrome.notifications.create(...);
});

const store = createStore(rootReducer,
  applyMiddleware(
    aliases
  )
);

tshaddix avatar Apr 20 '18 16:04 tshaddix

Somewhat. I was thinking we take it a step further and return an action creator that can be called either on the background or content script and will always execute in the background. Something like this:

// ===========
// background.js
// ===========

import { applyMiddleware, createStore } from 'redux';
import { aliases } from 'react-chrome-redux';

// effectively initializes all aliases/creators
import 'creators';

const store = createStore(rootReducer,
  applyMiddleware(
    aliases
  )
);

// ============
// creators/index.js
// ============

import { aliases } from 'react-chrome-redux';

export const userClickedAlias = aliases.createAlias('user-clicked-alias', () => {
  // do whatever
});

export const userExit = () => {
  return { type: 'some_action' };
};

// ========
// content.js
// ========

import { wrapStore } from 'react-chrome-redux';

import { userClickedAlias } from 'creators';

const store; // a normal Redux store

const wrappedStore = wrapStore(store, {
  portName: 'MY_APP',
  serializer: payload => JSON.stringify(payload, dateReplacer),
  deserializer: payload => JSON.parse(payload, dateReviver)
});

// actually ferries request to background
wrappedStore.dispatch(userClickedAlias());

Now you can use userClickedAlias either on the content script or background page. When you use it in a content script, it will simply try to ferry the user-click-alias message to the background and will call the function passed in (granted it was initialized in the background of course). You can now keep all action creators in the same file and it will make sense that no matter where you call the alias functions, they'll get executed in the background.

vhmth avatar Apr 22 '18 00:04 vhmth

While this might not be as much of a problem in Chrome extensions, something worth considering is the potential issue of having action creators defined both in the background script and the content script(s). See https://github.com/hardchor/electron-redux/issues/92 for more detail. Essentially we need the ability to declare and define aliased actions separately somehow, but hopefully not with duplicated code.

percyhanna avatar Sep 06 '18 17:09 percyhanna