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

Using with Redux Toolkit #245

Open
princesust opened this issue Apr 4, 2020 · 14 comments
Open

Using with Redux Toolkit #245

princesust opened this issue Apr 4, 2020 · 14 comments

Comments

@princesust
Copy link

princesust commented Apr 4, 2020

When I try to use redux toolkit, alias is dispatched and corresponding function is also called but after that showing an error
wrapStore.js:97 Error: Actions must be plain objects. Use custom middleware for async actions.

Below are full code
import { configureStore, getDefaultMiddleware } from "@reduxjs/toolkit";
import { wrapStore, alias } from "webext-redux";
import logger from "redux-logger";
import rootReducer from "./Reducers";

const aliases = {
"user-clicked-alias": () => {
console.log("user-clicked-alias");
},
};

const store = configureStore({
reducer: rootReducer,
middleware: [...getDefaultMiddleware(), logger, alias(aliases)],
});
wrapStore(store);

@pabloat81
Copy link

Same error using aliases, any fix?

@walleXD
Copy link

walleXD commented Aug 18, 2020

@princesust @pabloat81 aliases need to go first as they are intercepting and remapping fired actions to aliased ones. Then they remapped actions pass through middleware / reducer. If you put alias at the end, the remapped actions don't do anything cuz you are at the end of the middleware stack and then they jus go through the reducers

@pabloat81
Copy link

Hi @walleXD, thanx for the response.

I only have the code similar to the example of readme.md and get that error (any idea what i am doing wrong?):

import {applyMiddleware ,createStore} from 'redux';
import rootReducer from './reducers';
import {alias, wrapStore} from 'webext-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
'contact-selected-alias': () => {
// this call can only be made in the background script
chrome.browserAction.setBadgeText({text: "+"});
chrome.browserAction.setBadgeBackgroundColor({color: 'red'});
}
};

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

wrapStore(store);

@pabloat81
Copy link

@walleXD

Something i forgot to mention is that the alias gets executed aside the warning or error message.

Regards.

@charlie632
Copy link

Getting the same error using RTK. The alias is executing correctly, so no problem there, only the error

@charlie632
Copy link

Found a solution... In the alias you need to return the action

const aliases = {
  ['accounts/queryAccounts']: (action: PayloadAction<QueryPayload>) => {
    // do stuff
    return action; // Return this
  },
};

@GeekaholicLin
Copy link

Is there an example using webext-redux with RTK?
When I import store into background.js and using wrapStore(store) as below, it throws an error Unchecked runtime.lastError: Could not establish connection. Receiving end does not exist.

import { initStore } from '@/store';
import { wrapStore } from 'webext-redux';

const store = initStore(); // this will use `configureStore` and `createSlice` to init
wrapStore(store);

@tknickman
Copy link

tknickman commented Oct 27, 2021

I use webext-redux with RTK. It's an internal extension, so I can't publish the full source code unfortunately. But here's my store code if it's helpful for you!

import {
  configureStore,
  getDefaultMiddleware,
  combineReducers,
  Action,
} from '@reduxjs/toolkit';
import { alias, wrapStore } from 'webext-redux';
import { ThunkAction, ThunkMiddleware } from 'redux-thunk';
import logger from 'redux-logger';
import reducerMap from './slices';
import aliasMap from './aliases';

const rootReducer = combineReducers(reducerMap);
export type BackgroundState = ReturnType<typeof rootReducer>;

const store = configureStore({
  reducer: rootReducer,
  middleware: [
    alias(aliasMap),
    ...getDefaultMiddleware<BackgroundState>(),
    process.env.NODE_ENV !== 'production' && logger,
  ].filter(Boolean) as ThunkMiddleware<BackgroundState>[],
});

const { dispatch } = store;
wrapStore(store);

export type BackgroundDispatch = typeof store.dispatch;
export type BackgroundThunk = ThunkAction<
  void,
  BackgroundState,
  unknown,
  Action<string>
>;

export { store };
export default dispatch;

@buryo
Copy link

buryo commented May 11, 2022

@tknickman Is there a way to use Redux DevTools for debugging state in background.js?

@tknickman
Copy link

@buryo not to my knowledge, but using things like redux-logger are pretty helpful for seeing state changes in the background scripts.

@seanwessmith
Copy link

I use webext-redux with RTK. It's an internal extension, so I can't publish the full source code unfortunately. But here's my store code if it's helpful for you!

import {
  configureStore,
  getDefaultMiddleware,
  combineReducers,
  Action,
} from '@reduxjs/toolkit';
import { alias, wrapStore } from 'webext-redux';
import { ThunkAction, ThunkMiddleware } from 'redux-thunk';
import logger from 'redux-logger';
import reducerMap from './slices';
import aliasMap from './aliases';

const rootReducer = combineReducers(reducerMap);
export type BackgroundState = ReturnType<typeof rootReducer>;

const store = configureStore({
  reducer: rootReducer,
  middleware: [
    alias(aliasMap),
    ...getDefaultMiddleware<BackgroundState>(),
    process.env.NODE_ENV !== 'production' && logger,
  ].filter(Boolean) as ThunkMiddleware<BackgroundState>[],
});

const { dispatch } = store;
wrapStore(store);

export type BackgroundDispatch = typeof store.dispatch;
export type BackgroundThunk = ThunkAction<
  void,
  BackgroundState,
  unknown,
  Action<string>
>;

export { store };
export default dispatch;

Hey @tknickman, do you mind informing me/us of a couple more things.

do you add API to the middleware and the reducer?

const store = configureStore({
  reducer: {
    foo: fooReducer,
    [api.reducerPath]: api.reducer,
  },
  middleware: (getDefaultMiddleware) =>
    getDefaultMiddleware().concat(api.middleware).concat(logger),
});

wrapStore(store);

do you call your API directly in the react component?

  const {
    data,
    error,
    isLoading,
  } = useGetDataQuery({
foo:"bar"
  });

@tknickman
Copy link

tknickman commented Aug 16, 2024

@seanwessmith it's been ages so I had to go dig up the code for this. I configured the API calls using aliases.

In the store I setup the aliases as middleware:

const store = configureStore({
  reducer: rootReducer,
  middleware: [
    alias(aliasMap),
	// ... other middleware
});

And then I have a bunch of aliases defined. Here's one item in the map as an example:

'alias/fetch-data': (
    action: PayloadAction<{
      tabId: number;
      data: { version: string; name: string; env: string };
    }>,
  ): BackgroundThunk => (dispatch: BackgroundDispatch): AnyAction => {
    const { data, tabId } = action.payload;
    // call async API and dispatch result to a slice (we'll call it `slice-x`)
    fetchFromAPI({
        dispatch,
        ...
      });
    }

    return { type: 'alias/fetch-data' };
  },

Then I use this in a component with:

const dispatch = useDispatch();
// get the data that will store the result of the fetch
const data =
    useSelector(state => get(state, ['slice-x', type, id])) ?? {};

// put this wherever you need it (event handler, effect, etc)
dispatch({
   type: 'alias/fetch-data',
   payload: {
     ...
   },
})

That's how I did it 4 years ago (and haven't touched the code since). Hope that helps!

@seanwessmith
Copy link

Haha yea I know its been awhile, really appreciate the find and share. thanks a lot!

@loxator
Copy link

loxator commented Sep 12, 2024

@seanwessmith Did you get RTK-Query working with webext-redux? I am facing an issue where I get promiseRef.current?.unsubscribe is not a function when I try to run the hook which does the query. Would be great if there was an example provided on how to go about this one 😅

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

9 participants