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

feat: add ability to provide function in identity requests (fixes #177) #192

Merged
merged 1 commit into from
Aug 13, 2018
Merged

feat: add ability to provide function in identity requests (fixes #177) #192

merged 1 commit into from
Aug 13, 2018

Conversation

ipanasenko
Copy link
Contributor

This PR fixes #177

It's now possible to pass a function to identity request's value prop:

const fetchUser = id => fetch(`/users/${id}`);

connect(props => ({
  user: {
    value: () => fetchUser(props.match.params.id),
    comparison: props.match.params.id
  }
}))(Profile);

@ryanbrainard
Copy link
Contributor

Thanks for working on this! Looks good at first glance, but will look into the tests and corner cases a little more later.

Since someone could have theoretically provided a function before, I guess this should be considered a breaking change..

Oh, can you update the API doc and readme for this change too?

@ipanasenko
Copy link
Contributor Author

@ryanbrainard updated docs

@slorber
Copy link

slorber commented Jan 11, 2018

@ipanasenko @ryanbrainard can we publish this as beta on npm? I'd be happy to test that implementation on a real project

@ipanasenko
Copy link
Contributor Author

@slorber I was very lazy, so I just built dist and copied it into my project's node_modules. You can fetch my branch and do the same ;)

@ipanasenko
Copy link
Contributor Author

@slorber or modify your package.json to look like this: "react-refetch": "ipanasenko/react-refetch#feat/identity-function-dist",

@ryanbrainard
Copy link
Contributor

@slorber @ipanasenko I just published this as a beta release: react-refetch@2.0.0-0

@slorber
Copy link

slorber commented Jan 12, 2018

thanks,

i've just tested and it seems to work fine

Copy link
Contributor

@ryanbrainard ryanbrainard left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I just realized a small wrinkle in all of this. I think it can be solved just by documentation, but here it is:

If an app does not implement comparison, the default implementation compares value, so that means that if the value function is created inside of the connection function, it will be re-created every time and be considered a change. For example, in the documented example:

connect(props => ({
  usersFetch: {
    value: () => someAPI.list('/users')
  }
}))(Users)

someAPI.list('/users') is going to get called every time because a new function is created every time.

Compare that to:

const valueFunc = () => someAPI.list('/users')
connect(props => ({
  usersFetch: {
    value: valueFunc
  }
}))(Users)

Here valueFunc is created externally, so the function itself doesn't change. In fact, because comparison is not implemented it won't ever be called again.

As long as both comparison and value are set when value is a function, it should work as expected, but I can see this biting someone because it's not very obvious. At a minimum, we should make that clearer in the docs, but also thinking if we should enfore that as a rule or at least a warning. Thoughts?

Also, in the example above, it would probably be better show fetching a single user so there is something easy to compare:

connect(props => ({
  userFetch: {
    comparison: props.userId,
    value: () => someAPI.getUser(`/users/${props.userId}`)
  }
}))(Users)

})
})

it('should invoke value() only if `comparison` changed', (done) => {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

test name dupe. this looks like this was an accidential copy/paste of another test

```jsx
connect(props => ({
usersFetch: {
value: () => someAPI.list('/users')
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What about changing to fetching a single user with a comparison on the props.userId so it's more obvious when the function is called again?

const valueSpy = expect.createSpy(() => ({}))
@connect(({ foo }) => ({
testFetch: {
value: valueSpy,
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

even though it won't actually change the behavior of the test, consider changing to value: () => { valueSpy() } to better test the function being created inside (like most apps would do), while still having the spy outside (so your test works)

@ryanbrainard
Copy link
Contributor

@ipanasenko I just pushed up some changes to https://github.com/heroku/react-refetch/compare/stage-2.0.0. I updated the docs and tests as I mentioned in my review. If you're happy with them, we could merge them as-is (or of course push any changes you don't like). Then we can do the warnings (if we want them... interested to hear your thoughts) in a separate PR.

@slorber
Copy link

slorber commented Jan 15, 2018

@ryanbrainard maybe it's worth issuing a warning in dev in case function change over time and comparison is not provided

@ryanbrainard
Copy link
Contributor

I finally dusted this off and added the 'Request object with functional 'value' must also declare 'comparison' invariant to the stage-2.0.0 branch. I'll merge that into master shortly.

@ryanbrainard
Copy link
Contributor

Published as beta v2.0.0-3

@ryanbrainard ryanbrainard merged commit f980766 into heroku:master Aug 13, 2018
@ryanbrainard
Copy link
Contributor

Published in v2.0.0

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

Successfully merging this pull request may close these issues.

Allow value in identity requests to be a function
3 participants