title: Redux mapStateToProps: dispatch action to close popup after async update
body: <p>I pass state to my component as such:  </p>
  
  <pre><code>const mapStateToProps = (state, ownProps) =&gt; { 
      return { 
          pageState: state.pageState
      } 
  } 
  </code></pre>
  
  <p>The pageState contains information on the 'page', i.e. page meta data (such as page-name), and it also receives the method that was used when an async CRUD operation has updated the page data ("PUT").  </p>
  
  <p>The React component is a modal window that the user calls when (s)he wants to update and save the page name.<br>
  The async PUT operation works fine and the pageState gets properly updated (no problem here), but I don't understand from where I should dispatch the "hideModal" action that is executed <strong>after</strong> the async call.  </p>
  
  <p>Options are: </p>
  
  <ol>
  <li>mapStateToProps: check here if the pageState contains "PUT", then dispatch the close action;  </li>
  <li>From the render method: but this is discouraged; </li>
  <li>From <code>shouldComponentUpdate</code>. However, I bumped into a strange bug when testing this; the <code>mapStateToProps</code> doesn't appear to update the <code>this.props.pageState</code> properly on the first request. It only works on the second (?). Also, I don't feel like I should put it here anyhow; shouldComponentUpdate should not have side-effects like this.  </li>
  </ol>
  
  <p>My code to connect the component from the container:  </p>
  
  <pre><code>const renameModal = connect( 
      mapStateToProps, 
      mapDispatchToProps
  )(RenameModal); 
  </code></pre>
  
  <p>Any help? </p>
  
  <p>For info: I use Redux-saga for the async call. This shouldn't matter though. Updates of page info can happen from different places in my app, and this specific action (closing the modal) should stay decoupled from the implementation that takes care of the server requests. </p>
  
  <p>Redux-saga, listening for async update requests: </p>
  
  <pre><code>function* updatePage(action){
      try{ 
          const page = yield call(Api.updatePage, action.payload.siteSlug, action.payload.pageId, action.payload.page); 
          yield put({type: 'PUT_PAGE_SUCCEEDED', page}); 
      }catch(error){ 
          yield put({type: 'PUT_PAGE_FAILED', error}); 
      } 
  } 
  
  export function* watchUpdatePage(){ 
      yield* takeLatest('PUT_PAGE_REQ', updatePage); 
  } 
  </code></pre>
  
  <p>The reducer: </p>
  
  <pre><code>const asyncReducer = (state = pageState, action) =&gt; { 
      switch(action.type){ 
          case 'GET_PAGE_SUCCEEDED': 
              console.log("get page succeeded"); 
              return Immutable.fromJS({ 
                  type: "GET_PAGE_SUCCEEDED", 
                  method: "GET", 
                  pageState: action.page
              }); 
  
          case 'PUT_PAGE_SUCCEEDED': 
              console.log("put page succeeded"); 
              return Immutable.fromJS({ 
                  type: "PUT_PAGE_SUCCEEDED", 
                  method: "PUT", 
                  pageState: action.page
              }); 
  
          default: 
              return state; 
      }
  }
  </code></pre>