title: Data from redux-store visible in chrome dev tools but cannot actually access
body: <p>I'm using react with redux, implementing redux-thunk for an action that does the following:</p>
  
  <ol>
  <li>Thunk calls <code>axios.get()</code></li>
  <li>First <code>then()</code> statement maps over JSON to convert keys and values to front end specifications</li>
  <li>Second <code>then()</code> statement iterates over one property on JSON (0 - 5 items) creating an array of <code>axios.get()</code>calles, wrapped in promises, for each. This array is passed to an <code>async/wait</code> function ensuring these promises are all resolved before moving on.</li>
  <li>Third <code>then()</code> statement iterates over list again, removing any undefined values, and then fires off action creator successfully. Logging the data here on Chrome dev tools verifies that all data is present, and there are no unresolved promises.</li>
  <li>Logging this payload in Chrome dev tools from the reducers and into the container, which maps over data, results in the same issue. Data is present in console, but not accessible anywhere.</li>
  </ol>
  
  <p>I'll provide the working js below, although it does not work in this snippet:</p>
  
  <p><div class="snippet" data-lang="js" data-hide="false" data-console="true" data-babel="false">
  <div class="snippet-code">
  <pre class="snippet-code-js lang-js prettyprint-override"><code>/* - - - - - - Actions - - - - - - -
  
  Using thunk, promises, and async/await to insure data is present before sending to reducer 
  
  */
  
  export function getSingleMessage(id, callback) {
    return function (dispatch) {
      const request = axios.get(`${ROOT_URL}getDialogue.php?message_id=${id}`)
      .then((resp) =&gt; {
        // Just reformatting JSON
        const { data } = resp;
        console.log('message: ', data)
        let formValues = {};
        let messageIds = [];
  
        formValues.dialogue_query = data.message_query;
        formValues.dialogue_text = data.message;
        formValues.message_id = data.messages_id;
        if (data.attachment) {
          formValues.attachment_text = data.attachment.text;
          formValues.attachment_fallback = data.attachment.fallback;
          formValues.image_url = data.attachment.image_url;
          if (data.attachment.actions) {
            /* 
              1) these buttons need unique id's
              2) the last unique id needs to not collide with any other id's of new buttons
  
              // Map through actions
                if key is 'name'
                  button_text
                if key is 'type'
                  action
            */
            
            let key = 0;
            
  
            formValues.buttons = data.attachment.actions.map( action =&gt; {
              let newAction = {};
              
              Object.keys(action).forEach( key =&gt; {
                let curr = action[key];
                let newCurrArr;
                let newCurr;
                if (key === 'name') {
                  newAction.button_text = curr;
                }
                
                if (key === 'value') {
                  if (curr.includes('Value[')) {
                    newCurrArr = curr.split('=');
                    newCurr = newCurrArr.pop();
                    newAction.button_action = newCurr;
                    curr = newCurrArr.join('=')
                    console.log('CURRRRRRR: ', curr)
                  }
                  if (curr.includes('message_id=')) {
                    newCurrArr = curr.split('=').pop();
                    console.log('NEWCURRARR: ', newCurrArr)
                    let newNewCurrArr = newCurrArr.split('&amp;');
                    console.log('NEWNEWCURRARR: ', newNewCurrArr)
                    newCurr = newNewCurrArr.shift();
                    messageIds.push(newCurr);
                    newAction.message_id = Number(newCurr);
                    
                  }
                }
              });
  
              newAction.id = key;
              key++;
              return newAction;
            })
          }
        }
        return [formValues, messageIds]
      })
      .then((resp) =&gt; {
      // creating array of promises, and resolving with async/await
        const formValues = resp[0];
        const messageIds = resp[1];
  
        const promises = messageIds.map((id) =&gt; axios.get(`${ROOT_URL}getDialogue.php?message_id=${id}`));
        console.log('PROMISES!!!!!! ', promises)
  
        if (formValues.buttons) {
          async function getPreviewMessages() {
            let resolvedPreviewMessages = await Promise.all(promises);
            return formValues.buttons.map((button, i) =&gt; {
            // setting previewMessages to buttons
              button.previewMessage = resolvedPreviewMessages[i];
              return button;
            })
          }
          getPreviewMessages();
        } 
        return formValues;
      })
      .then((formValues) =&gt; {
        // 
        console.log('RESP: ', formValues)
        // cleans up any null or undefined values
        
        for (let key in formValues) {
          if (formValues[key] === 'null' || formValues[key] === 'undefined') {
            formValues[key] = '';
            console.log(`formValues[${key}] = ${formValues[key]}`);
          }
          console.log(`formValues[${key}] = ${formValues[key]}`);
        }
        console.log('formValues: ', formValues)
  
        dispatch(fireOffSingleMessage({data: formValues}));
      })
      .catch((err) =&gt; {
        console.log(err)
        return err;
      })
      console.log('requesssssssst: ', request)
      callback();
      
    }
  }
  
  function fireOffSingleMessage(request) {
    // data is all resolved in Chrome Dev Tools
     console.log('FIRED OFF SINGLE MESSAGE~~~~~~', request)
    return {
      type: GET_SINGLE_MESSAGE,
      payload: request,
    }
  }
  
  // - - - - - - Reducer - - - - - - -
  
  import { GET_SINGLE_MESSAGE, REFRESH_SINGLE_MESSAGE, ADD_BUTTON_EDIT, EDIT_BUTTON_EDIT, DELETE_BUTTON_EDIT } from '../constants';
  
  export default (state = {}, action) =&gt; {
   switch(action.type) {
    case GET_SINGLE_MESSAGE: 
    console.log('Data is present!: ', action.payload.data.buttons)
     return action.payload;
    case REFRESH_SINGLE_MESSAGE:
     return {}
        
      // Not involved
    case ADD_BUTTON_EDIT:
     console.log('ADD_BUTTON_EDIT reducer fired off!', state);
     if (Array.isArray(state.data.buttons) &amp;&amp; state.data.buttons.length &gt; 0) {
       return {
         ...state, 
         data: {... state.data, buttons: [...state.data.buttons, action.button]}
       };  
     } else {
       return {
         ...state, 
         data: {... state.data, buttons: [action.button]}
       }; 
     }
    case EDIT_BUTTON_EDIT:
    console.log('EDIT_BUTTON_EDIT reducer fired off!', state);
     const newStateEdit = state.data.buttons.map(button =&gt; {
       if (button.id === action.button.id) {
        console.log('button.id: ', button.id)
        console.log('action.button.id: ', action.button.id)
         return action.button;
       } else {
         return button;
       }
     })
     return {
       ...state, 
       data: {... state.data, buttons: newStateEdit}
     }; 
    case DELETE_BUTTON_EDIT:
    console.log('DELETE_BUTTON_EDIT reducer fired off!', state);
     const newStateDelete = state.data.buttons.filter(button =&gt; button.id !== action.target);
     return {
       ...state, 
       data: {... state.data, buttons: newStateDelete}
     }; 
    default:
     return state;
   }
  }
  
  // - - - - Root Reducer - - - - -
  
  import { combineReducers } from 'redux';
  import { reducer as formReducer } from 'redux-form';
  
  import getAllDialogs from './getAllDialogs-reducer.js';
  import handleMessages from './messages-reducer.js';
  import handleMessage from './message-reducer.js'
  import handleMessageId from './messageId-reducer.js'
  import updateButtons from './buttons-reducer.js';
  import renderButtonForm from './buttonForm-reducer.js';
  import handleId from './buttonId-reducer.js';
  import handleNewMessageQuery from './newMessageQuery-reducer.js';
  import handleMessageQueries from './messageQueries-reducer.js';
  import handleButton from './button-reducer.js';
  import handleReRenderToggle from './reRenderToggle-reducer.js';
  import handleContext from './context-reducer.js';
  
  const rootReducer = combineReducers({
    dialogs: getAllDialogs,
    messages: handleMessages,
    message: handleMessage,
    messageId: handleMessageId,
    buttons: updateButtons,
    buttonForm: renderButtonForm,
    button: handleButton,
    buttonId: handleId,
    reRender: handleReRenderToggle,
    newMessageQuery: handleNewMessageQuery,
    messageQueries: handleMessageQueries,
    context: handleContext,
    form: formReducer,
  });
  
  export default rootReducer;
  
  // - - - - - container - - - - - 
  
  
    renderFakeButtons(buttons = []) {
      const _that = this;
      buttons.forEach((button, i) =&gt; {console.log(button)});
      const { history, deleteButton, renderButtonForm, reRenderToggle, getSingleMessage, getSinglePreviewMessage } = this.props;
      // DATA LOGS IN DEV TOOLS!!!!
      console.log('BUTTONS: ', buttons)
      return buttons.map((button) =&gt; {
        // DATA LOGS IN DEV TOOLS!!!
        console.log('BUTTON: ', button)
        return (
          &lt;div 
            className="top-margin"
            key={button.id}&gt;
            &lt;div className="row"&gt;
              &lt;Card&gt;
              &lt;CardHeader
                title={`Button Text: ${button.button_text}`}
                subtitle={`Button Action: ${button.button_action}`}
                actAsExpander={true}
                showExpandableButton={true}
              /&gt;
              &lt;CardText expandable={true}&gt;
                &lt;div&gt;
  {/*THIS IS WHERE I WOULD ACCESS THE PROPERTY EXPLICITLY*/}
                  {JSON.stringify(button)}
                &lt;/div&gt;
              &lt;/CardText&gt;
              &lt;CardActions&gt;
                &lt;FlatButton 
                  label={`Next Message: ${button.message_id}`} 
                  onTouchTap={function(){
                      getSingleMessage(button.message_id, () =&gt; {
                        history.push(`/message/edit/${button.message_id}`);
                      })
                    }
                  }
                /&gt;
                &lt;FlatButton 
                  label="Delete Button"
                  onTouchTap={() =&gt; { deleteButton(button.id, 'edit'); reRenderToggle(); }} 
                /&gt;
              &lt;/CardActions&gt;
              &lt;/Card&gt;
            &lt;/div&gt;
  
          &lt;/div&gt;
        )}
      );
    }
    
    render() {
  
      const _that = this;
      const { state, onSubmit, onTest, onBack, renderMessageQuerySelect, renderInputFields, renderTextAreaFields, injectButtonForm, renderUserTestSelectOptions } = this;
      const { messages, getMessageId, messageId, handleSubmit, renderButtonForm, buttons, reset, buttonForm, refreshSingleMessage, toggleMessageQueryField, newMessageQuery, initialValues, addButtons } = this.props;
  
      let titleName;
  
      if (messages.messages &amp;&amp; messages.messages.dialog_name) {
        titleName = messages.messages.dialog_name;
      } else if (messages.messages &amp;&amp; messages.messages.messageQuery) {
        titleName = messages.messages.messageQuery
      }
  
      return (
        &lt;div&gt;
          &lt;MuiThemeProvider&gt;
  
            &lt;div className="row"&gt;
              &lt;div className="col-md-6"&gt;
                &lt;form onSubmit={handleSubmit(onSubmit.bind(this))}&gt;
                  &lt;div className="form-group"&gt;
                  &lt;h4&gt; Edit Message {messageId} from "{titleName}" &lt;/h4&gt;
                    &lt;Field
                      label="Message Query"
                      name="dialogue_query"
                      component={newMessageQuery ? renderInputFields : renderMessageQuerySelect.bind(this)}
                    /&gt;
                    New
                    &lt;input  
                      type="checkbox"
                      onClick={toggleMessageQueryField}
                    /&gt;
                  &lt;/div&gt;
                  &lt;Field
                    label="Text of Message"
                    name="dialogue_text"
                    component={renderTextAreaFields}
                  /&gt;
                  &lt;Field
                    label="Attachment Text"
                    name="attachment_text"
                    component={renderInputFields}
                  /&gt;
                  { state.error !== null ? &lt;div className="form-group has-danger"&gt;&lt;div className="text-help"&gt;{state.error}&lt;/div&gt;&lt;/div&gt; : null }
                  &lt;Field
                    label="Attachment Fallback"
                    name="attachment_fallback"
                    component={renderInputFields}
                  /&gt;
                  { state.error !== null ? &lt;div className="form-group has-danger"&gt;&lt;div className="text-help"&gt;{state.error}&lt;/div&gt;&lt;/div&gt; : null }
                  &lt;Field
                    label="Image Url"
                    name="image_url"
                    component={renderInputFields}
                  /&gt;
                  &lt;div className="form-group"&gt;
                    &lt;div&gt;
                      &lt;div
                        className="btn btn-primary"
                        onClick={function() {
                          renderButtonForm(); 
                        }}
                      &gt;
                        Click to Add Buttons
                      &lt;/div&gt;
                      
                      &lt;div&gt;
                      { initialValues &amp;&amp; initialValues.buttons ? _that.renderFakeButtons(initialValues.buttons) : '' }
                      &lt;/div&gt;
  
                    &lt;/div&gt;
                  &lt;/div&gt;
  
                  &lt;Field
                    label="Test Primary User"
                    name="primary_test_user_id"
                    component={renderUserTestSelectOptions}
                  /&gt;
                  &lt;Field
                    label="Test Secondary User"
                    name="secondary_test_user_id"
                    component={renderUserTestSelectOptions}
                  /&gt;
                  &lt;button 
                    type="submit" 
                    className="btn btn-primary"
                  &gt;
                    Submit
                  &lt;/button&gt;
                  &lt;button 
                    type="submit" 
                    className="btn btn-primary buttons-margin"
                    onClick={handleSubmit(onTest.bind(this))}
                  &gt;
                    Test
                  &lt;/button&gt;
                  &lt;div className="btn btn-primary buttons-margin" onClick={reset}&gt;Reset to Original&lt;/div&gt;
                  &lt;div className="btn btn-danger buttons-margin" onClick={onBack.bind(this)}&gt;Back&lt;/div&gt;
                &lt;/form&gt;
              &lt;/div&gt;
              &lt;div className="col-md-5"&gt;
                &lt;div className="row"&gt;
                  &lt;div className="col-md-12"&gt;
                    {injectButtonForm(buttonForm)}
                  &lt;/div&gt;
                &lt;/div&gt;
                &lt;div className="row"&gt;
                  &lt;div className="col-md-12"&gt;
                    &lt;div className="bottom-top-margin"&gt;
  
  
  
                    &lt;/div&gt;
                  &lt;/div&gt;
                &lt;/div&gt;
              &lt;/div&gt;
            &lt;/div&gt;
          &lt;/MuiThemeProvider&gt;
        &lt;/div&gt;
      );
    }
  }
  
  function validate(values) {
    const errors = {};
    if (!values.dialogue_text) {
      errors.dialogue_text = "Enter message text";
    }
  
    return errors;
  }
  
  MessageEdit = reduxForm({
    validate,
    form: 'MessageEditForm', // a unique name for this form
    enableReinitialize: true,
  })(MessageEdit)
  
  MessageEdit = connect(
    state =&gt; { 
      const newState = {
      dialogs: state.dialogs,
      messages: state.messages,
      messageId: state.messageId,
      initialValues: state.message.data,
      buttonForm: state.buttonForm.isRendered,
      buttonId: state.buttonId, 
      messageQueries: state.messageQueries,
      reRender: state.reRender,
      newMessageQuery: state.newMessageQuery,
      context: state.context,
    }
    console.log('MessageEdit newState: ', newState);
    return newState },
    { addButtons, postNewMessage, testMessage, getSingleMessage, refreshSingleMessage, deleteMessage, getDialogMessages, refreshButtons, deleteButton, refreshButtonId, refreshButtons, renderButtonForm, unRenderButtonForm, toggleMessageQueryField, getMessageId, getMessageQueries, reRenderToggle }
  )(MessageEdit)
  
  export default MessageEdit;</code></pre>
  <pre class="snippet-code-html lang-html prettyprint-override"><code>&lt;script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react.min.js"&gt;&lt;/script&gt;
  &lt;script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react-dom.min.js"&gt;&lt;/script&gt;</code></pre>
  </div>
  </div>
  </p>
  
  <p>Why is my data available in my THUNK, according to Chrome dev tools, but not actually accessible?</p>