1

If there is data in Redux store that needs to sent to server by dispatching an async action, how to dispatch it without having to receive it inside of a React component because this data is not used for rendering anything.

Example:

My store:

{
  dataNotUsedForRendering: 'A',
  dataUsedForRendering: 'B'
}

My component:

class MyComponent extends React.Component {
    //...

    render(){
        const {dataUsedForRendering, dataNotUsedForRendering, dispatch} = this.props;

     return (
     <div>
        {dataUsedForRendering}
        <button onClick={()=> dispatch({type: 'SAVE', payload: dataNotUsedForRendering})}>Save</button>
     </div>);
    }
}

export const mapStateToProps = (state) => ({
    dataUsedForRendering: state.dataUsedForRendering,
    dataNotUsedForRendering: state.dataNotUsedForRendering
});

export default connect(mapStateToProps)(MyComponent);

Here dataNotUsedForRendering is being received as a prop inside MyComponent just for the purpose of sending it to server.

I tried mapDispatchToProps but I get the props of Connect(MyComponent) and not MyComponent.

Frozen Crayon
  • 5,172
  • 8
  • 36
  • 71
  • redux-thunk have `getState` which can load your entire state in a action. But it is not recommended to load the state that way. – TryingToImprove Feb 05 '18 at 18:27
  • @TryingToImprove I'm trying to improve (pun intended) and since I'm using `getState` in every action creator the I need data to reach an endpoint (tokens, etc...), I wanted to know why is it not recommended to load the state that way? Which alternative would you recommend? In the past I've created a helper that [`subscribes`](https://redux.js.org/docs/api/Store.html#subscribe) to redux's store, and updates [`axios' default headers`](https://github.com/axios/axios#global-axios-defaults) but I found it too hard to add exceptions to that approach. – Maximo Dominguez Feb 05 '18 at 18:38
  • 1
    @MaximoDominguez you can use `getState` in your thunk for this. See: https://stackoverflow.com/a/43260654/2479481 There are some concerns with this approach in the community (which you can read about above), but you should feel free to use it if it makes sense for you. – Luke Willis Feb 05 '18 at 18:52
  • As @LukeMWillis says, it is a way to load data, but I think that you should try and limit it it's use. – TryingToImprove Feb 06 '18 at 07:46

2 Answers2

1

Here's how you would accomplish that with redux-thunk. Your component would change so that it knows nothing about dataNotUsedForRendering, and imports a save action:

import { save } from './actions';

class MyComponent extends React.Component {
    render() {
        const {dataUsedForRendering, dispatch} = this.props;

        return (
            <div>
                {dataUsedForRendering}
                <button onClick={() => dispatch(save())}>Save</button>
            </div>
        );
    }
}

export const mapStateToProps = (state) => ({
    dataUsedForRendering: state.dataUsedForRendering
});

export default connect(mapStateToProps)(MyComponent);

Then your action:

export const save = () => (dispatch, getState) => {
    dispatch({
        type: 'SAVE',
        payload: getState().dataNotUsedForRendering
    });
};

Edit: but you probably don't need to do this. You could just access/modify your dataNotUsedForRendering in your reducer. If you're just grabbing this data out of the store to save it in another section of the state, consider normalizing your store and processing your actions across multiple reducers as appropriate.

Luke Willis
  • 8,429
  • 4
  • 46
  • 79
  • My use case is that I need to send it to server. I use `redux-saga` so perhaps I could import store (the output of `createStore`) and do a `getState` on that. – Frozen Crayon Feb 06 '18 at 10:12
  • @ArjunU I wouldn't recommend that approach. Where is the data coming from? Is it entered into a form or something? – Luke Willis Feb 06 '18 at 15:46
  • The data does originate from a form. At any given time only a little of it is rendered or updated but I have to send the whole data to server for every change. Sounds like bad design but it's not for other reasons. – Frozen Crayon Feb 06 '18 at 17:52
  • Just found out that there's a `yield select` API in redux saga to access store – Frozen Crayon Feb 06 '18 at 18:28
1

Redux saga equivalent of @LukeMWillis' answer:

const selectDataNotUsedForRendering = state => state.dataNotUsedForRendering;

const dataNotUsedForRendering = yield select(selectDataNotUsedForRendering);

yield put({
  type: 'SAVE',
  payload: dataNotUsedForRendering
});
Frozen Crayon
  • 5,172
  • 8
  • 36
  • 71