-
-
Notifications
You must be signed in to change notification settings - Fork 350
Add Observer render and inject sugar #387 #403
Conversation
Just a hint, it might be easier to review this if you turn off Prettier :) (or perhaps eslint autofix?). Any kind of reformatting should be done in a separate PR in my opinion. And I love this, that's mostly what I suggested in #387 Edit: Oh and would you mind updating Typescript definitions as well? |
@FredyC hhhh, i very appreciate your suggestion ,so i did it and will update typescript definitions later |
Yea, you are right, husky is not installed so |
@Sunshine168 Thanks for the PR! @FredyC's PR is merged, could you rebase? PR looks good :). One remaining question; could you update the Readme as well describing this alternative syntax? |
Also, it's obvious that using |
i will rebase later , i am still in working |
4c0173b
to
13b416d
Compare
done ! |
README.md
Outdated
@@ -82,7 +82,7 @@ It takes as children a single, argumentless function which should return exactly | |||
The rendering in the function will be tracked and automatically re-rendered when needed. | |||
This can come in handy when needing to pass render function to external components (for example the React Native listview), or if you | |||
dislike the `observer` decorator / function. | |||
|
|||
And it can work with `Provider` use inject and render property / or just takes as children, detail in Example2.(PS:using children has a priority than render , so dont use at the same time) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I would split this, there are two concerns to cover - render prop and injecting. Also, I have a trouble understanding what it says. Let me rephrase this.
In case you are a fan of render props, you can use that instead of children. Be advised, that you cannot use both approaches at once, children have a precedence.
Here goes example showing render prop only
Observer can also inject the stores simply by passing a selector function.
Second example with inject
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Oh and with injecting it's worth to show an example that passing strings work same way as with inject
HoC.
README.md
Outdated
class App extends React.Component { | ||
render() { | ||
return ( | ||
<Provider h="hello" w="world"> |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Are you sure you can pass a string as a store prop? I am not aware that it would turn to observable automagically here. In that case, it's kinda misleading example.
src/observer.js
Outdated
|
||
Observer.displayName = "Observer" | ||
|
||
Observer.propTypes = { | ||
render: (propValue, key, componentName, location, propFullName) => { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
DRYing this would be nice :)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
ennnn Any suggestion to diy Observer.propTypes
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Well, if you look closely, it's the same function except for that first condition. Which doesn't make any sense to me. It means, that when checking render
prop, you are telling it's ok if children
prop is a function. That doesn't make any sense to me.
README.md
Outdated
@@ -82,7 +82,7 @@ It takes as children a single, argumentless function which should return exactly | |||
The rendering in the function will be tracked and automatically re-rendered when needed. | |||
This can come in handy when needing to pass render function to external components (for example the React Native listview), or if you | |||
dislike the `observer` decorator / function. | |||
|
|||
And it can work with `Provider` use inject and render property / or just takes as children, detail in Example2.(PS:using children has a priority than render , so dont use at the same time) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Oh and with injecting it's worth to show an example that passing strings work same way as with inject
HoC.
@FredyC Ohhhh very thank you for your help .tat now will be better? |
README.md
Outdated
const Comp = () => ( | ||
<div> | ||
<Observer | ||
inject={store => ({ h: store.h, w: store.w })} | ||
render={props => <span>{`${props.h} ${props.w}`}</span>} | ||
render={() => <span>hello world</span>} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Hm, not very good example since there is nothing to observe :D Perhaps pass some variable in props to Comp and use that in render so it makes more sense.
README.md
Outdated
Example2: | ||
In case you are a fan of render props, you can use that instead of children. Be advised, that you cannot use both approaches at once, children have a precedence. | ||
|
||
Here goes example showing render prop only |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Well, I did not mean this line to be included there as well, that's why I used italic ;)
src/observer.js
Outdated
|
||
Observer.displayName = "Observer" | ||
|
||
Observer.propTypes = { | ||
render: (propValue, key, componentName, location, propFullName) => { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Well, if you look closely, it's the same function except for that first condition. Which doesn't make any sense to me. It means, that when checking render
prop, you are telling it's ok if children
prop is a function. That doesn't make any sense to me.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We are getting there, some small tweaks are remaining.
README.md
Outdated
@@ -105,6 +103,56 @@ React.render(<App person={person} />, document.body) | |||
person.name = "Mike" // will cause the Observer region to re-render | |||
``` | |||
|
|||
In case you are a fan of render props, you can use that instead of children. Be advised, that you cannot use both approaches at once, children have a precedence. | |||
|
|||
Here goes example showing render prop only |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This line is a bogus one, I did not mean to include it by using italic text :)
README.md
Outdated
|
||
Observer can also inject the stores simply by passing a selector function. | ||
|
||
Example with inject |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Same for this line, it's redundant imo.
@@ -349,12 +349,41 @@ function mixinLifecycleEvents(target) { | |||
} | |||
|
|||
// TODO: support injection somehow as well? | |||
export const Observer = observer(({ children }) => children()) | |||
export const Observer = observer(({ children, inject: observerInject, render }) => { | |||
const component = children || render |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I am thinking if there shouldn't be some warning if both props are used. Perhaps that's what you had in mind with that propTypes check? Except you need to return message describing a problem. Returning undefined means it's valid.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
ennn , thinging, first i prefer show warning by propTypes if both props
and coding like this
const ObserverPropsCheck = (props,key,componentName,location,propFullName)=>{
const extraKey = key === "children" ? "render" : "children"
if(typeof propValue[key] === "function" && typeof propValue[extraKey] === "function" ){
return new Error("Invalid prop,do not use children and render in the same time in`" + componentName )
}
if (typeof propValue[key] === "function" || typeof propValue[extraKey] === "function") {
return
}
return new Error(
"Invalid prop `" +
propFullName +
"` of type `" +
typeof propValue[key] +
"` supplied to" +
" `" +
componentName +
"`, expected `function`."
)
}
'>< but seem complexity
or do same props check in Observer Component instead in propType
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yea, checking with prop types like this is probably enough. I don't think it adds complexity, it's a friendly behavior toward user.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
great !
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@mweststrate I think we are good to go here :)
README.md
Outdated
<div> | ||
{this.props.person.name} | ||
<Observer | ||
render={(props) => <div>{props.person.name}</div>} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
props
work without inejction?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Good catch, this is an oversight. It should refer to this.props
instead.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Sorry ,a stupid fault zzzzzz should refer to this.props
Great work @Sunshine168 and thanks for the extensive reviews @FredyC and @Gvozd ! Will release tomorrow |
This is broken. Results in |
@mvestergaard That's an unfortunate oversight. Could you send in the PR please? Some tests for this should be probably included as well. |
Just released 4.4.1, that should fix the issue. Unclear yet why this passed the tests, so if somebody could add a test testing the prop types checking that would be appreciated :D |
No description provided.