John Doe John Doe - 1 month ago 14
React JSX Question

How to access dynamic data inside @connect decorator of react-redux-connect?

So, I am using react-async-connect in combination with react-redux-connect, as such:

@asyncConnect([{
deferred: true,
promise: ({ params, store: { dispatch, getState } }) => {
if (!isLoaded(getState(), params.userID)) {
console.log('it was not already loaded')
return dispatch(loadProfile(params.userID))
}

console.log('it was indeed already loaded')

},
}])
@connect(
state => ({
profile: {???},
error: state.publicData.profile.error,
loading: state.publicData.profile.loading,
}),
{ initializeWithKey }
)
export default class Profile extends Component {
...etc


Basically, the
asyncConnect
fires an action that loads the pertinent data, and then I'm using the @connect decorator to load this data as props for the
Profile
component below. The trouble is, I want to load user profile data into my store based on the userId, so the location of the data is "dynamic". How can I access
params
or other globalState type things inside the @connect decorator?

What I need, supposing the user's id is 1234, is something like this:

@connect(
state => ({
profile: state.publicData.users.1234,
error: state.publicData.profile.error,
loading: state.publicData.profile.loading,
}),
{ initializeWithKey }
)


Of course, that userId is in the
params
object, as well as in the route itself. How can I access this?

EDIT:

So I should have looked more carefully at the docs. It turns out you can pass a second
ownProps
argument, like so:

@connect(
(state, ownProps) => ({
profile: state.publicData.users[ownProps.params.userId],
error: state.publicData.profile.error,
loading: state.publicData.profile.loading,
}),
{ initializeWithKey }
)

Answer

The router is not being processed into the state - you should be able to do this in your reducer.js file like so:

reducer.js

...
import { routerStateReducer } from 'redux-router';

export default combineReducers({
  router: routerStateReducer,
...
})

This should put all of your router information into the state, and make it accessible to your connect function:

component.js

@connect(
  state => ({
    profile: state.publicData.users[state.router.params.userId],
    error: state.publicData.profile.error,
    loading: state.publicData.profile.loading,
  }),
  { initializeWithKey }
)

This code would assume you have the userId and always will, otherwise this won't work.

Also - based on your update - the ownProps should have access to the params as well -

@connect(
  (state, ownProps) => ({
    profile: state.publicData.users[ownProps.params.userId],
    error: state.publicData.profile.error,
    loading: state.publicData.profile.loading,
  }),
  { initializeWithKey }
)