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(react): add connect React HOC #116

Merged
merged 2 commits into from
Apr 2, 2020
Merged

feat(react): add connect React HOC #116

merged 2 commits into from
Apr 2, 2020

Conversation

tlaundal
Copy link
Contributor

@tlaundal tlaundal commented Mar 19, 2020

A higher order component for connecting react components to streams.
Builds upon the useStream hook, and is intended for use in class based components that can't use the hook themselves.

Rigid testing with react-test-renderer, which renders the components without a DOM. Have also chosen to not write any tsx, so we won't have to deal with more tooling.

@tlaundal tlaundal added the work-in-progress Work in progress label Mar 19, 2020
@tlaundal tlaundal self-assigned this Mar 19, 2020
@tlaundal tlaundal changed the base branch from react-connect to master April 1, 2020 10:06
@tlaundal tlaundal removed the work-in-progress Work in progress label Apr 1, 2020
src/react/connect.ts Show resolved Hide resolved

// Typescript doesn't recognize this as Observed & Props for some reason
// Question on StackOverflow: https://stackoverflow.com/q/60758084/1104307
const newProps = { ...props, ...value } as Props & Observed;
Copy link
Contributor

Choose a reason for hiding this comment

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

Isn't the precedence in the current connect (from streamUtils) the opposite? (...value, ...props)

Copy link
Contributor

Choose a reason for hiding this comment

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

Nice catch @holographic-principle.

Personally, I don't see a strong case for why "props" or "streamedProps" should take precedence 🤷‍♂ Did you switch these around for any particular reason @tlaundal ?

In general, I can't think of a case where having the same key defined in "props" and "streamedProps" is a good pattern as I think this could cause a lot of confusion. Perhaps we could add a warning in dev mode?

Copy link
Contributor Author

@tlaundal tlaundal Apr 2, 2020

Choose a reason for hiding this comment

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

So actually, this kind of shadowing is actually caught by TS because of the types (this is what the Omit does), so I don't really think this is a problem.

I can change the order to be the same as in ardoq-front, just to be on the safe side, but I don't think we should document or test this, as it is explicitly forbidden by the types.

EDIT: Actually, It should be the way I have already defined it, and it should be tested.
Take this example:

const WrappedComponent = (props: { msg: string, num: number }) => (<p>{msg}</p>);
const HOComponent = connect(WrappedComponent, of({ msg: "from stream" }));

const illegal = <HOComponent num={1} msg="direct overshadowing gives type error" />;

const props = { num: 2, msg: "indirect overshadowing does actually not give error" };
const legal = <HOComponent {...props} />;

The illagal line here is the behaviour we wish for. legal is a work around for the type error, but I think it makes sense to follow the idea of the Omit typing:

Only properties which are not supplied by the stream can be supplied manually

I will add a test and a sentence documenting it, but I don't see the need for a dev mode warning.

Copy link
Contributor

Choose a reason for hiding this comment

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

Ok, good 👍

Copy link

@chriskr chriskr left a comment

Choose a reason for hiding this comment

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

LGTM

Component: ComponentType<Props>,
stream$: Observable<Observed>
) => (props: Omit<Props, keyof Observed>) => {
const value = useStream(stream$);
Copy link
Contributor

@anton164 anton164 Apr 1, 2020

Choose a reason for hiding this comment

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

I think I remember you mentioned that this would solve connectWithProps as well, do you have an example of that or will that be a next step?

Copy link
Contributor

Choose a reason for hiding this comment

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

I'm purely guessing here, but I think Tobias' intention might have been to replace connectWithProps with the HoC from this PR. That would explain the order in which props vs streamedProps are spread. However this is (potentially) not backwards-compatible with connect.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

connectWithProps use properties as a part of the stream (usually filtering). The useStream hook can be used in it's place.
This HOC cannot replace connectWithProps because the properties are not available when the stream is initialized.

I'll create a PR in ardoq-front where I replace connectWithProps with useStream today.

Copy link
Contributor

@anton164 anton164 left a comment

Choose a reason for hiding this comment

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

Looks good! 👍

A warning in dev mode for key collision in "props" and "streamedProps" would be nice :)

@tlaundal
Copy link
Contributor Author

tlaundal commented Apr 2, 2020

I have clearified in the documentation and with tests the precendence of passed/forwarded props and streamed props. Will merge in about half an hour.

@tlaundal tlaundal merged commit c9e350a into master Apr 2, 2020
@tlaundal tlaundal deleted the react-connect-HOC branch April 2, 2020 10:05
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.

None yet

4 participants