Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Access store from context? #1123

Closed
badtant opened this issue Dec 13, 2018 · 14 comments
Closed

Access store from context? #1123

badtant opened this issue Dec 13, 2018 · 14 comments

Comments

@badtant
Copy link

@badtant badtant commented Dec 13, 2018

Hi, I just updated to 6.0.0 and have a question. I can't really figure out from the docs how to access the store from context anymore.

My app is wrapped with
<Provider store={store}>

Then in any component I could access it with

MyComponent.contextTypes = {
    store: PropTypes.object.isRequired
};

->

this.context.store

How do i achieve the same thing with 6.0.0?

@timdorr
Copy link
Member

@timdorr timdorr commented Dec 13, 2018

We use the new context API, which is exported as ReactReduxContext.

Loading

@timdorr timdorr closed this Dec 13, 2018
@badtant
Copy link
Author

@badtant badtant commented Dec 17, 2018

Got it working but this also seem to subscribe to updates from the store.
What I want is just access to the store that I created without subscribing to updates.

I can of course export it from where I created it. Is that the best way?

Loading

@markerikson
Copy link
Contributor

@markerikson markerikson commented Dec 17, 2018

What are you actually trying to accomplish?

Loading

@badtant
Copy link
Author

@badtant badtant commented Dec 17, 2018

I want to read a value from the store in componentWillUnmount.
So I want access to the store without subscribing to any updates.

Previously I got access with this.context.store.getState()

Loading

@markerikson
Copy link
Contributor

@markerikson markerikson commented Dec 17, 2018

Per the React docs on using context, you would either need to add a contextType field to your component so that you can access the context value as this.context, or have a wrapper component that renders a <Context.Consumer>, extracts the store, and passes it as a prop to your own component.

What kind of value are you needing to read from the store on unmount? Why not just connect the component, and extract that value in mapState as normal?

Loading

@badtant
Copy link
Author

@badtant badtant commented Dec 17, 2018

  • contextType is not supported with react-redux 6.0.0 if I understood correctly
  • mapState works but will subscribe me to updates I don't need
  • Context.Consumer also works but did also subscribe me to updates

I'm just trying to think as performant as possible. Hence not wanting to subscribe if I don't need all the updates.

Loading

@markerikson
Copy link
Contributor

@markerikson markerikson commented Dec 17, 2018

contextType is a React thing, not a React-Redux thing, and should work fine.

As I asked, what kind of value are you trying to use? Is it something that you expect will be changing frequently? Do you have specific reasons why you think connecting to get this value will be a performance issue? Why do you only need this in componentWillUnmount?

My general reaction here is that you're over-thinking the performance implications, but I can't say for sure because I don't know the specifics of your app and what you're trying to do.

Loading

@badtant
Copy link
Author

@badtant badtant commented Dec 17, 2018

Ok. I used contextType before upgrading to 6.0.0. When I upgraded it stopped working... The release notes said this:
"Any library that attempts to access the store instance out of legacy context will break, because we now put the store state into a <Context.Provider> instead."

The value I want to read is a string that does change quite a lot and in this component I only need it when it unmounts. It's used for statistics tracking in this case.
Maybe I'm overthinking but I always try to minimize the number of renders in my components. And since I got my case working as I wanted before I want it to work the same way now when upgrading.

Loading

@markerikson
Copy link
Contributor

@markerikson markerikson commented Dec 17, 2018

Note that contextTypes and contextType are not the same thing.

React defines legacy context using syntax like:

class MyComponent extends React.Component {}

MyComponent.contextTypes = {
    a : PropTypes.string,
    b : PropTypes.object
}

When the new context API was released, it originally could only be used via a render-props API:

<MyContext.Consumer>
{ (contextValue) => {
    // do stuff with the context value here
});
</MyContext.Consumer>

To help with the migration from old context to new context, the React team added a new way to access new context in 16.6 called contextType:

class MyClass extends React.Component {
  static contextType = MyContext;
  componentDidMount() {
    let value = this.context;
    /* perform a side-effect at mount using the value of MyContext */
  }
}

So, you should be able to do:

class MyComponent extends React.Component {
    static contextType = ReactReduxContext;

    componentWillUnmount() {
        const storeState = this.context.store.getState();
        // do something with the store state here
    }
}

Loading

@badtant
Copy link
Author

@badtant badtant commented Dec 17, 2018

Ahh, didn't know about that way :) Will try it first thing tomorrow.
Thanks!

Loading

@badtant
Copy link
Author

@badtant badtant commented Dec 18, 2018

contextType seem to work the same way as Context.Consumer in this case. meaning I get updates.
this.context now includes both store and storeState. is there a way to only get store?

Loading

@markerikson
Copy link
Contributor

@markerikson markerikson commented Dec 18, 2018

No, the React-Redux <Provider> puts both of those into the context.

Loading

@timdorr
Copy link
Member

@timdorr timdorr commented Dec 18, 2018

If you want that, you can just make your own context:

// StoreContext.js
import React from 'react'

export const StoreContext = React.createContext()

export default StoreContext
// app.js

import StoreContext from './StoreContext'

const store = createStore(reducer)

ReactDOM.render(
  <Provider store={store}>
    <StoreContext.Provider value={store}>
      <App />
    </StoreContext.Provider>
  </Provider>,
  root
)

The new API is really simple 👍

Loading

@tibbus
Copy link

@tibbus tibbus commented Feb 6, 2019

You can use ReactReduxContext from 'react-redux' :
Docs and example here : https://react-redux.js.org/api/provider

Loading

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Linked pull requests

Successfully merging a pull request may close this issue.

None yet
4 participants