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

How to pass parameter to selector? #772

Closed
jk2K opened this issue Jul 23, 2016 · 13 comments
Closed

How to pass parameter to selector? #772

jk2K opened this issue Jul 23, 2016 · 13 comments
Labels

Comments

@jk2K
Copy link
Contributor

jk2K commented Jul 23, 2016

I want to get channel with channelId prop

My code

const mapStateToProps = (state, ownProps) => {
  return {
    channelId: ownProps.params.channelId,
    channel: selectChannel()
  }
};

selectors

const selectHome = () => (state) => state.get('home');

const selectChannels = () => createSelector(
  selectHome(),
  (homeState) => homeState.get('channels')
);

const selectChannelId = () => (state, ownProps) => ownProps.params.channelId;

const selectChannel = () => createSelector(
  selectChannels(),
  selectChannelId(),
  (channels, channelId) => channels.find((channel) => channel.channel_id == channelId)
);

I console the channel

  componentDidMount() {
    console.log(this.props.channel);
    this.props.fetchMessages(this.props.channel);
  }

but i get below, non value, non derived data
image
Am I doing wrong?

@jk2K
Copy link
Contributor Author

jk2K commented Jul 23, 2016

I found below is work

const mapStateToProps = createStructuredSelector({
  channelId: selectChannelId(),
  channel: selectChannel()
});

What's the difference between the two?

const mapStateToProps = (state, ownProps) => {
  return {
    channelId: ownProps.params.channelId,
    channel: selectChannel()
  }
};

I must use createStructuredSelector function when i use reselect?

@sethmcleod
Copy link
Contributor

I believe you need to pass the selectors you are composing from as an array, like this:

const selectChannel = () => createSelector(
  [ selectChannels, selectChannelId ],
  (channels, channelId) => channels.find((channel) => channel.channel_id == channelId)
);

Check out this link for more info on using ownProps with Reselect: https://stackoverflow.com/questions/36392048/how-can-i-get-ownprops-using-reselect-on-redux/37404975#37404975

@jk2K
Copy link
Contributor Author

jk2K commented Jul 24, 2016

Check out this link
https://github.com/reactjs/reselect#createselectorinputselectors--inputselectors-resultfunc

const mySelector = createSelector(
  state => state.values.value1,
  state => state.values.value2,
  (value1, value2) => value1 + value2
)

// You can also pass an array of selectors
const totalSelector = createSelector(
  [
    state => state.values.value1,
    state => state.values.value2
  ],
  (value1, value2) => value1 + value2
)

they are the some

@igorbarbashin
Copy link

igorbarbashin commented Jul 26, 2016

You can also pass parameters right from mapStateToProps:

const mapStateToProps = createStructuredSelector({
  channel: selectChannelById(id) // Actually, it's not possible. Sorry for confusion 😅
});

Selector:

const selectChannelById = (id) => createSelector(
  selectChannels(),
  (channels) => channels.find((channel) => channel.channel_id == id)
);

But these kinds of selectors could be useful in sagas:

const channel = yield select(selectChannelById(id));

@mxstbr
Copy link
Member

mxstbr commented Jul 26, 2016

Since this question has been answered quite thoroughly I'll close this issue, but feel free to continue the conversation!

@mxstbr mxstbr closed this as completed Jul 26, 2016
@jk2K
Copy link
Contributor Author

jk2K commented Jul 27, 2016

@igorbarbashin , thanks

const mapStateToProps = createStructuredSelector({
  channel: selectChannelById(id)
});

but the id is in route params, I can get id using this.props.params.channelId

How can I pass it to selectChannelById ?

@igorbarbashin
Copy link

@jk2K Yeah, I wrote it and then understood that there's no access to that variable from mapStateToProps. As I then mentioned in the last line this selector could be used in redux-saga.

Your solution is what I actually use:

const mapStateToProps = createStructuredSelector({
  channelId: selectChannelId(), // Gets channel id from ownProps
  channel: selectChannel() // Gets stuff from store
});

@arjshiv
Copy link

arjshiv commented Aug 31, 2016

@jk2K and @igorbarbashin
Not sure if this is still active, but here's how I got around it for something not based on ownProps

Selectors

export const selectFileTypeIsUploading = () => createSelector(
  selectYourStateHere(),
  state => fileType => state.getIn(['uploading', fileType])
);

Component

MapStateToProps

createStructuredSelector({
  fileTypeIsUploading: selectFileTypeIsUploading()
});

propTypes

static propTypes = {
    fileTypeIsUploading: React.PropTypes.func,
  }

Usage

<FileUpload 
  title={uploadType}
  uploading={this.props.fileTypeIsUploading(uploadType)}
/>

@eromoe
Copy link

eromoe commented Sep 20, 2017

@arjshiv How to modify your code to support ownProps ?

@igorbarbashin
Copy link

igorbarbashin commented Sep 20, 2017

@eromoe I think it's like this:

const mapStateToProps = createStructuredSelector({
  something: (state, ownProps) => selectSomethingById(ownProps.id)(state, ownProps)
});

@arhtudormorar
Copy link

@eromoe I use it this way and it works:

const mapStateToProps = (state, ownProps) => createStructuredSelector({
  selectOptions: selectOptions({ selectId: ownProps.name, formKey: ownProps.form }),
});

@pohsiangchen
Copy link

@eromoe here is my solution and it works:

component/container

static propTypes = {
  match: PropTypes.object, // route parameter
};

const mapStateToProps = createStructuredSelector({
  member: makeSelectMemberById(),
});

selector

const selectMembers = (state) => state.get('members');

const makeSelectMemberById = () => createSelector(
  selectMembers,
  // state: redux store
  // props: connected component's props
  (state, props) => props.match.params.memberId,
  (members, memberId) => members.find((member) => member.id === memberId)
);

selector will recompute when the memberId changes

@lock
Copy link

lock bot commented May 28, 2018

This thread has been automatically locked since there has not been any recent activity after it was closed. Please open a new issue for related bugs.

@lock lock bot locked as resolved and limited conversation to collaborators May 28, 2018
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
Projects
None yet
Development

No branches or pull requests

8 participants