admin管理员组

文章数量:1318770

We have a ReactNative app that uses redux, redux-persist and a HeadlessJS task. This task needs to have access to the store. As the task fires without booting the entire app (and so has no access by default), we thought we could simply create the store inside the task as well so that it would be rehydrated by redux-persist. It turns out, however, that the store created in this way is different from the one in the app: after running, they contain different values. We tested this in several ways and it seems indeed a problem with the stores (and not with the actions for instance) How should we access a Redux store from an HeadlessJS task?

Relevant code: store/configure.js:

configureStore = (client) => {
  const middleware = createMiddleware(client);
  const finalCreateStore = applyMiddleware(thunk, middleware, logger)(createStore);
  const store = finalCreateStore(rootReducer, undefined, autoRehydrate());

  return store;
};

In use (both in the app and in the service):

const client = new ApiClient();
const store = configureStore(client);
client.setStore(store);
persistStore(store, {
  storage: AsyncStorage,
}

In the app we simply use the Provider from react-redux to use the store, in the service we use store.dispatch.

We have a ReactNative app that uses redux, redux-persist and a HeadlessJS task. This task needs to have access to the store. As the task fires without booting the entire app (and so has no access by default), we thought we could simply create the store inside the task as well so that it would be rehydrated by redux-persist. It turns out, however, that the store created in this way is different from the one in the app: after running, they contain different values. We tested this in several ways and it seems indeed a problem with the stores (and not with the actions for instance) How should we access a Redux store from an HeadlessJS task?

Relevant code: store/configure.js:

configureStore = (client) => {
  const middleware = createMiddleware(client);
  const finalCreateStore = applyMiddleware(thunk, middleware, logger)(createStore);
  const store = finalCreateStore(rootReducer, undefined, autoRehydrate());

  return store;
};

In use (both in the app and in the service):

const client = new ApiClient();
const store = configureStore(client);
client.setStore(store);
persistStore(store, {
  storage: AsyncStorage,
}

In the app we simply use the Provider from react-redux to use the store, in the service we use store.dispatch.

Share Improve this question asked Mar 3, 2017 at 17:16 JoranJoran 2112 silver badges5 bronze badges 2
  • For future searchers: as we weren't able to have it working within a reasonable timeframe, we went for a non-store based solution to exchange information between the app and the headless task. We used AsyncStorage, which works reliably between app and task. – Joran Commented Mar 13, 2017 at 8:50
  • 1 I stumbled across the same problem with an audio player App. Events from the audio player should still dispatch changes to the Redux store, even if it's in the background. – fraherm Commented Jul 14, 2017 at 13:50
Add a ment  | 

3 Answers 3

Reset to default 2

For people looking for solution. I have found the solution in here. The idea is to bind the store to async method.

https://github./react-native-kit/react-native-track-player/issues/63

Copy pasting the solution here.

// index
const store = ...
....registerHeadlessTask('TrackPlayer', () => require('event-handler.js').bind(null, store));
// event-handler.js
module.exports = async (store, data) {
    if(data.type == '...') {
        store.dispatch(...);
    }
};

simply create the store inside the task as well so that it would be rehydrated by redux-persist.

This did indeed happen.

You created two stores (not advisable with redux) which were both hydrate, but not linked, as there is no such thing as linked redux stores. Every time you run createStore, it's a new store. And every time you dispatch, you do that on a specific store.

Unfortunately async or multithreaded issues are not directly addressed by redux.

It would be possible though with middleware and / or store listeners to keep the two stores in sync.

But redux is also just not a mean for munication between threads (which I assume these tasks are, or you could just give the task a reference to the store once it was created or give the main app the store reference from the task).

It's more a form of Command-Query-Separation and centralized state.

You can access your store directly as reference.

Let's say you have your headless set in index.js, then you can just simply use store there like this:

    import { AppRegistry } from 'react-native';
    
    import Store from './src/Redux/Store';
    import { someAction } from './src/Redux/Actions/someActions';
        
    import App from './App';    
    import { name as appName } from './app.json';
    
    const HeadlessTask = async () => {
      console.log('Receiving HeadlessTask');
      const someParam = await Store.getState().Something.someParam;
    
      if (someParam) {
        Store.dispatch(someAction(someParam));
      } else {
        Store.dispatch(someAction());    
      }
    };
    
    AppRegistry.registerHeadlessTask('HeadlessTask', () => HeadlessTask);
    
    AppRegistry.registerComponent(appName, () => App);

本文标签: javascriptReact Native HeadslessJS and ReduxHow to access store from taskStack Overflow