Skip to content

Conversation

@evansiroky
Copy link
Contributor

@evansiroky evansiroky commented Nov 17, 2020

This PR depends on #201.

In response to #201 (comment), this PR refactors the app to avoid needless prop-drilling of custom components sent in by implementing applications by utilizing the React context as needed.

Although this PR doesn't yet have any commits that indicate a breaking change, there are changes that could be considered breaking. The itineraryClass, itineraryFooter, LegIcon and ModeIcon are now all supposed to be added to a components property in the ResponsiveWebapp instead of in individual components. This also introduces the assumption that implementers of otp-react-redux will use the ResponsiveWebapp or directly import the ComponentContext and wrap components in a Provider in their app.

@evansiroky evansiroky added the BLOCKED Blocked (waiting on another PR to be merged) label Nov 17, 2020
@evansiroky evansiroky self-assigned this Nov 17, 2020
@evansiroky evansiroky removed the BLOCKED Blocked (waiting on another PR to be merged) label Nov 20, 2020
@evansiroky evansiroky mentioned this pull request Nov 20, 2020
Copy link
Member

@landonreed landonreed left a comment

Choose a reason for hiding this comment

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

My primary comment (stated previously on a call, I think) is that perhaps we should allow users of this library to pass in LegIcon, ModeIcon or ItinType as a prop instead of context. And that we should perhaps not change the itineraryFooter name to avoid making this a breaking change.

@landonreed landonreed assigned evansiroky and unassigned landonreed Nov 30, 2020
Copy link
Collaborator

@binh-dam-ibigroup binh-dam-ibigroup left a comment

Choose a reason for hiding this comment

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

Conditional approval on mentioning ItineraryFooter in example.js. This PR begs the question on whether state.otp.config should be a context too, but I definitely agree with the approach.

Comment on lines +52 to +57
const components = {
ItineraryBody: DefaultItinerary,
LegIcon: MyLegIcon,
ModeIcon: MyModeIcon
}

Copy link
Collaborator

Choose a reason for hiding this comment

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

One of my first reactions as I am reading about React.Context is that all of state.otp.config could be moved to the context (it is read once a few lines above and set once for all to global state). What are your thoughts on that?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I was also thinking that, but it'd be a much larger change to instead include that in the context instead of the redux store. Also, perhaps some parts of the config might be changeable, for example if we ever implement a webapp with multiple languages, maybe it could have a config setting of the language that could change in the app.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

The more I think about it tho, maybe it would be good to consider the config being a global context thing that is assumed to not change. It could be useful to even explore adding some kind of context provider to otp-ui packages which would reduce the amount of prop-drilling and simplify the inclusion of config items throughout those components.

Comment on lines 190 to 191
const {isActive, route, operator} = this.props
const { ModeIcon } = this.context
Copy link
Collaborator

Choose a reason for hiding this comment

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

Inconsistent spacing between braces.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Fixed in 91bdbb5.

// define some application-wide components that should be used in
// various places
const components = {
ItineraryBody: DefaultItinerary,
Copy link
Collaborator

Choose a reason for hiding this comment

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

I think ItineraryFooter should be mentioned here, at least as a commented-out attribute, so implementers know that it is possible to provide a footer if they so wish.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Improved above comment to note ItineraryFooter in 91bdbb5.

@binh-dam-ibigroup binh-dam-ibigroup removed their assignment Nov 30, 2020
@evansiroky
Copy link
Contributor Author

@landonreed, in response to your comment

My primary comment (stated previously on a call, I think) is that perhaps we should allow users of this library to pass in LegIcon, ModeIcon or ItinType as a prop instead of context. And that we should perhaps not change the itineraryFooter name to avoid making this a breaking change.

The more I think of this, the more I'm thinking this is kind of a take-it-or-leave-it PR. If we want to keep this behavior for any of the *Panel components, then this would re-introduce the prop-drilling problem. If it's for the final components that use the context, it may not be possible for end-users to configure these properly without reintroducing prop-drilling since some components like RouteRow in RouteViewer aren't exported directly.

However, it is possible for an end-user to still use components directly without being inside the ResponsiveWebapp component. I have added some comments about how to do this in 91bdbb5. In all reality, it seems unlikely that any end-user would import individual components directly given how tightly tied to redux the components in this repo are.

@evansiroky
Copy link
Contributor Author

Ready for review again, and I'm reassigning @binh-dam-ibigroup to consider #274 (comment).

Copy link
Collaborator

@binh-dam-ibigroup binh-dam-ibigroup left a comment

Choose a reason for hiding this comment

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

LGTM.

@binh-dam-ibigroup binh-dam-ibigroup removed their assignment Dec 2, 2020
@landonreed
Copy link
Member

@evansiroky, your comment about providing the config as context to otp-ui components made me think of this: if components like the StopViewer (or others that make use of context) were to migrate to otp-ui, how would we handle providing them with the context? Maybe this is just a bridge we cross when we get there, but just wanted to get the thought down.

@landonreed landonreed assigned evansiroky and unassigned landonreed Dec 3, 2020
@evansiroky
Copy link
Contributor Author

@evansiroky, your comment about providing the config as context to otp-ui components made me think of this: if components like the StopViewer (or others that make use of context) were to migrate to otp-ui, how would we handle providing them with the context? Maybe this is just a bridge we cross when we get there, but just wanted to get the thought down.

I'm changing my mind again and thinking that maybe slots is actually better for otp-ui after all. Currently, otp-rr already sends appropriate components defined in the context like this:

class ConnectedSettingsSelectorPanel extends Component {
static contextType = ComponentContext
render () {
const {
config,
query,
setQueryParam,
showUserSettings
} = this.props
const { ModeIcon } = this.context
return (
<div className='settings-selector-panel'>
<div className='modes-panel'>
{showUserSettings && <UserTripSettings />}
<StyledSettingsSelectorPanel
ModeIcon={ModeIcon}
queryParams={query}
supportedModes={config.modes}
supportedCompanies={config.companies}
onQueryParamChange={setQueryParam}
/>
</div>
</div>
)
}
}

Since each otp-ui package kind of stands by itself, it seems like it could be more work and unfriendly to first-time users to have to wrap it in a context provider in order for the package to work. Perhaps within each package it could make sense to use the context API to reduce prop-drilling inside the components in the package.

@evansiroky evansiroky assigned landonreed and unassigned evansiroky Dec 4, 2020
@landonreed landonreed assigned evansiroky and unassigned landonreed Dec 4, 2020
@evansiroky evansiroky merged commit 98c3142 into dev Dec 4, 2020
evansiroky added a commit that referenced this pull request Jan 5, 2021
BREAKING CHANGE:

- Refactor various components and example.js file to more heavily use React's context API (see #274)
- Update to use latest config schema compatible with opentripplanner/core-utils v3 (see #201)
@github-actions
Copy link
Contributor

github-actions bot commented Jan 8, 2021

🎉 This PR is included in version 2.0.0 🎉

The release is available on:

Your semantic-release bot 📦🚀

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants