question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

Accessing the store without @connect-ing?

See original GitHub issue

Is there currently a way for a component to access the root Provider store without being connect-ed to it? It sounds like it might be a bit of an anti-pattern, but I’m not sure. I’ve a couple of circumstances where I can see it coming in handy (dumb components which can still query related data from prop).

Issue Analytics

  • State:closed
  • Created 8 years ago
  • Comments:29 (15 by maintainers)

github_iconTop GitHub Comments

59reactions
gaearoncommented, Sep 16, 2015

If you really really need store, grab it from context like connect() does it.

class MyComponent {
  someMethod() {
    doSomethingWith(this.context.store);
  }
}

MyComponent.contextTypes = {
  store: React.PropTypes.object.isRequired
};
25reactions
rodryquinterocommented, Feb 10, 2016

Ok, here is the code. I am just pasting the relevant parts (ommitted lots of import calls). Thanks for looking into this @gaearon

app.js (look at the OrderContainer component)

import React from 'react';
// import { DevTools, DebugPanel, LogMonitor } from 'redux-devtools/lib/react';
import ReactDOM from 'react-dom';
import { Provider } from 'react-redux';
import { createHistory } from 'history';

// do not start app until cache-login is resolved
login().then((response) => {


  // perform login in intervals to mantain session
  loginInterval();

  const store = createStore();

  // create history object for "onEnter" hooks
  const history = createHistory();

  function onUpdate() {
    store.dispatch(navigate());
  }

  const NoRoute = (props) =>{
    window.location = "#auth/orders/list";
    return <span/>;
  };


  ReactDOM.render(<div>
    <div id="redux-devtools container">
      <Provider store={store}>
        <Router onUpdate={onUpdate}>
          <Route path="/" component={App}>
            <IndexRoute component={NoRoute}/>
            <Route path="auth" onEnter={checkAuthRoute}>

              {/* DASHBOARD */}
              <Route path="dashboard">
                <Route path="main" component={DashboardMain}/>
              </Route>

              {/* ORDERS */}
              <Route path="orders">
                <Route path="list" component={OrdersContainer}/>
                <Route path="form(/:id)" component={OrderContainer}/>
                <Route path="new" component={OrderContainer}>
                  <Route path="patient(/:id)" component={PatientContainer}/>
                </Route>
                <Route path="trace/:tableRelated" component={TraceAuditContainer}/>
              </Route>
              {/* PATIENTS */}
              <Route path="patients">
                <Route path="list" component={PatientsContainer}>
                  <Route path="new(/:id)" component={PatientContainer}/>
                </Route>
              </Route>
              {/* APPOINTMENTS */}
              <Route path="appointments">
                <Route path="calendar" component={ApptsCalendarContainer}>
                  <Route path="date/:date" component={ApptsCalendarModalContainer}/>
                </Route>
                <Route path="collection" component={ApptsSampleCollectContainer}/>
              </Route>

              {/* CONF */}
              <Route path="conf" onEnter={checkAdmin} history={history}>
                <Route path="general" component={ConfGeneral}/>
                <Route path="calendar" component={ConfCalendar}/>
                <Route path="demo_order" component={ConfOrderDemographics}/>
                <Route path="demo_patient" component={ConfPatientDemographics}/>
                <Route path="test_prereqs" component={ConfTestPreReqs}/>
                <Route path="bcprinters" component={ConfBCPrinters}/>
              </Route>
            </Route>
            <Route path="login" component={LoginContainer} />
          </Route>
        </Router>
      </Provider></div>
      {/*}<DebugPanel top right bottom>
      <DevTools store={store} monitor={LogMonitor} />
    </DebugPanel>*/}
  </div>,
  document.getElementById('root')
  );
})
.catch(function (error) {
    throw(error);
}).done();

order-container.jsx

import React, { PropTypes } from 'react';
import { createHistory, useBeforeUnload } from 'history';
import { connect } from 'react-redux';
...

import ConfirmNavMixin from '../util/mixin-confirm-nav';

const OrderContainer = React.createClass({

  mixins: [ Lifecycle, ConfirmNavMixin ],

  getInitialState: function() {
    return {
      showPrintModal: false
    };
  },

  getCustomFieldValues(fields, props) {
    return fields.map(field => {
      _.each(props, (value, key) => {
        if (field.label == key) {
          field.value = value;
        }
      });

      return field;
    });
  },

  fetchOrder(id) {

    // lock record
    lock_record('CITAS.wsORDERS.cls',20000, id).then((obj) => {
      this.lockObj = obj;

      // if lock was not succesfull, clear interval
      if (!this.lockObj.locked) {
        clearInterval(this.lockObj.intervalToken);
      }
    });

    this.props.dispatch(get_order(id));
  },

  componentWillUnmount() {
    // clear lock interval
    if (typeof(this.lockObj) !== 'undefined') {
      clearInterval(this.lockObj.intervalToken);
    }

    this.props.dispatch(initial_order_state());
  },

  componentWillMount() {

    const { params, dispatch } = this.props;

    dispatch(get_tests());

    // ** get appointments for current month and year
    const month = moment().format("MM");
    const year = moment().format("YYYY");

    dispatch(get_appts_monyear(month, year));

    if (params.id) {
      this.fetchOrder(params.id);
    }
    else {
      dispatch(initial_order_state_noloading());
    }
  },

  componentWillReceiveProps(nextProps) {
    if (nextProps._showPatientModal) {
      nextProps.dispatch(not_show_patientmodal());
      nextProps.history.pushState(null, 'auth/orders/new/patient/' + nextProps.patientid);
    }
  },

  onBlurOrderID(orderID) {
    const { confOrderNo, printedBarcode, dispatch, _lastOrderID } = this.props;

    const compOrderID = get_orderno(orderID, confOrderNo);

    if (compOrderID != _lastOrderID) {
      dispatch(get_order(compOrderID));
    }
  },

  handleSubmit(data) {

    const { dispatch, _recordPulled, _printBarcodeAuto, printedBarcode,
       _printWorkOrderAuto, activeBCPrinter, orderID } = this.props;

    const tests = _.map(this.props.tests, (test) => {
      return {TestID: test.TestID};
    });

    delete data.test_listbox;
    data.tests = JSON.stringify(tests);
    const bcPrintSettings = { activeBCPrinter, _printBarcodeAuto, printedBarcode };

    dispatch(save_order(data, _recordPulled, bcPrintSettings));

    // automatic  work order printing
    if (_printWorkOrderAuto) {
      this.onClickPrint();
    }
  },

  handleClickNew() {

    const { dispatch, history } = this.props;
    const url = "/auth/orders/new";
    history.pushState("",url);
    dispatch(initial_order_state_noloading());
  },

  onClickPrint() {

    const { conf, firstName, lastName, dob, patientid, tests, orderID, registerDate, sex,
      appointmentDate, OrderField1, OrderField2, OrderField3, OrderField4, intl } = this.props;

    const data = { firstName, lastName, dob, patientid, tests, orderID, registerDate, sex,
      appointmentDate, OrderField1, OrderField2, OrderField3, OrderField4 };


    data.tests = _.chain(tests)
    .filter((test) => {
      return test.Profile == "0";
    })
    .groupBy((test) => {
        var section = (test.SectionName) ? test.SectionName : intl.messages.other;
        return section;
    })
    .value();

    // save order data in localStorage
    localStorage.setItem("CITAS.printOrder",JSON.stringify(data));

    const url = 'print.html?order-template';
    window.open(url,'_blank');
  },

  handleBlurPatientID(value, name) {
    const { dispatch } = this.props;

    dispatch(set_order_value(name,value));
    dispatch(get_order_patient(value));
  },

  handleClickPrintBarcode() {
    const { dispatch, activeBCPrinter, orderID } = this.props;

    dispatch(print_barcode(orderID, activeBCPrinter));
  },

  render () {

    const { browser, locale, confOrderNo, orderID, registerDate, appointmentDate, firstName, lastName,
      tests, testCatalog, dob, patientid, age, sex, _recordPulled, dispatch, history, customFields,
      selectedTest, disabledDates, calendarConf, appointments, sentToHost, priority, OrderField1,
      OrderField2, OrderField3, OrderField4, OrderField5, OrderField6, OrderField7, OrderField8,
      OrderField9, OrderField10, activeBCPrinter, _printBarcodeAuto, _printWorkOrderAuto, _showLoading } = this.props;

    // compute order number according to configuration
    const compOrderID = (_recordPulled) ? orderID : get_orderno(orderID, confOrderNo);

    const customFieldAndValues = this.getCustomFieldValues(customFields, this.props);

    return (<div ref="div">
            <Loader isLoading={_showLoading}>
              <OrderForm
                ref="order_container"
                confOrderNo={confOrderNo}
                _printWorkOrderAuto={_printWorkOrderAuto}
                _printBarcodeAuto={_printBarcodeAuto}
                onToggleConfItem={(item) => dispatch(toggle_conf(item))}
                calendarConf={calendarConf}
                appointments={appointments}
                browser={browser}
                history={history}
                locale={locale}
                orderID={compOrderID}
                patientid={patientid}
                registerDate={registerDate}
                priority={priority}
                sentToHost={sentToHost}
                appointmentDate={appointmentDate}
                lastName={lastName}
                firstName={firstName}
                customFields={customFieldAndValues}
                sex={sex}
                tests={tests}
                dob={dob}
                age={age}
                onViewDateChange={(date,moment,view) => dispatch(get_appts_monyear(moment.format("MM"),moment.format("YYYY")))}
                onChangeValue={(name,value) => dispatch(set_order_value(name,value))}
                onClickNew={() => this.handleClickNew()}
                selectedTest={selectedTest}
                testCatalog={testCatalog}
                onSubmit={this.handleSubmit}
                onBlurOrderID={this.onBlurOrderID}
                onBlurPatientID={this.handleBlurPatientID}
                onClickPrint={this.onClickPrint}
                onClickPrintBarcode={this.handleClickPrintBarcode}
                _recordPulled={_recordPulled}
              />
            </Loader>
              {this.props.children}
            </div>);
  }
});

OrderContainer.contextTypes = _.extend(OrderContainer.contextTypes, {
 store: PropTypes.object.isRequired
});

function select(state) {

  const confOrderNo = {
    digits: state.conf.digits,
    prefix: state.conf.prefix,
    suffix: state.conf.suffix,
    prefixType: state.conf.prefixType,
    suffixType: state.conf.suffixType
  };

  confOrderNo.totalDigits = calc_orderdigits(confOrderNo);

  return {
    _hasChanged: diff_state(state.order),
    activeBCPrinter: state.bcprint_modal.activeBCPrinter,
    appointments: state.appointments.list,
    calendarConf: state.conf.calendarConf,
    disabledDates: state.appointments.disabledDates,
    browser: state.conf.browser,
    conf: state.conf,
    locale: state.language.lang,
    sentToHost: state.order.sentToHost,
    firstName: state.order.firstName || "",
    lastName: state.order.lastName || "",
    printedBarcode: state.order.printedBarcode,
    registerDate: state.order.registerDate,
    priority: state.order.priority,
    dob: state.order.dob,
    tests: state.order.tests,
    age: calc_age(state.order.dob),
    sex: state.order.sex,
    patientid: state.order.patientid,
    orderID: state.order.orderID,
    appointmentDate: state.order.appointmentDate,
    customFields: state.conf_demographics.customOrderFields,
    OrderField1: state.order.OrderField1,
    OrderField2: state.order.OrderField2,
    OrderField3: state.order.OrderField3,
    OrderField4: state.order.OrderField4,
    OrderField5: state.order.OrderField5,
    OrderField6: state.order.OrderField6,
    OrderField7: state.order.OrderField7,
    OrderField8: state.order.OrderField8,
    OrderField9: state.order.OrderField9,
    OrderField10: state.order.OrderField10,
    confOrderNo: confOrderNo,
    _lastOrderID: state.order._lastOrderID,
    _showLoading: state.order._showLoading,
    _recordPulled: state.order._recordPulled,
    _error: state.order._error,
    _showPatientModal: state.order._showPatientModal,
    _printBarcodeAuto: state.order._printBarcodeAuto,
    _printWorkOrderAuto: state.order._printWorkOrderAuto,
    testCatalog: state.tests.testCatalog,
    selectedTest: state.tests.selectedTest
  };
}

export default injectIntl(connect(select)(OrderContainer));

Feel free to critique anything that you see wrong/unusual 😃

Read more comments on GitHub >

github_iconTop Results From Across the Web

react-redux: how do you access the store from 'anywhere ...
In the react-redux documentation it states that when using React-redux and connect() importing the store is not recommended.
Read more >
Accessing the Store | React Redux
Accessing the Store. React Redux provides APIs that allow your components to dispatch actions and subscribe to data updates from the store.
Read more >
If you can't connect to the App Store, iTunes Store, or other ...
Learn what to do if you see a "Cannot connect" message, if an app won't load anything, or if content stops downloading.
Read more >
Access the Redux Store Outside a React Component
It's simple to get access to the store inside a React component – no need to pass the store as a prop or...
Read more >
Configure access to Microsoft Store (Windows 10)
AppLocker provides policy-based access control management for applications. You can block access to Microsoft Store app with AppLocker by ...
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Hashnode Post

No results found