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鈥檒l occasionally send you account related emails.

Already on GitHub? Sign in to your account

Code review #4

Open
thibaudcolas opened this Issue Jan 21, 2019 · 0 comments

Comments

Projects
None yet
1 participant
@thibaudcolas
Copy link

thibaudcolas commented Jan 21, 2019

Alright! 馃檪 I generally don't have the chance to review a whole package, that was a lot of fun. In the end I tried to be as exhaustive as possible with my comments, but a lot of it is fairly minor / quick to address.

I made the review as a pull request that contains all of the package's code, over at thibaudcolas#1, so it would be easier to relate comments to code. But I also summarised most of the comments below, so they are easier to relate to one another, and prioritise. It's probably easier to first read this list, then the comments in the PR.

I also made a PR to address some of the issues below (packaging, dev tools, and API), over at #5, along with the corresponding changes to Wagtail in a branch that builds upon wagtail/wagtail#4942.

Potential problems

These are the code-level problems I would expect to cause the most pain / actual bugs. They are ordered by how important I think they are to address sooner rather than later.

Performance

Error handling

Generally I haven't seen much error handling code. I would expect the inner script execution to be the most problematic, since it will be very common for third-party code to break.

Minor ones

Minor but still sources of concern


Packaging - build & dependenceies

The general problem here is that the library is compiled as if it was an app, instead of a library, with all of its dependencies bundled instead of resolved by npm on install.

Bonus points

  • Consider using sass (official Dart implementation) to get rid of the annoying native code compilation of node-sass. (thibaudcolas#1 (comment))
  • Consider configuring transform-react-remove-prop-types to wrap proptypes instead of removing them, as for a project like this they can be very useful in dev mode. (thibaudcolas#1 (comment))
  • Remove unused @babel/cli (thibaudcolas#1 (comment))
  • Consider replacing @babel/plugin-proposal-decorators and decorators syntax with normal higher-order functions/components. (thibaudcolas#1 (comment))

Documentation

To me this is what would be the most worthy of documentation. The blockDefinitions schema is probably this package鈥檚 most important API, and the polyfills are its least obvious requirements.

Development & demo env

Styles

Accessibility

I'm sure the current StreamField implementation isn't particularly SR-friendly, so we're not aiming super high, but there are obvious improvements to be made here.

react-redux

react-redux recently released its v6, which uses the new React context API from React 16.4, and introduces a change in behavior that affects this package:

[...] there is a behavior change around dispatching actions in constructors / componentWillMount. Previously, dispatching in a parent component's constructor would cause its children to immediately use the updated state as they mounted, because each component read from the store individually. In version 6, all components read the same current store state value from context, which means the tree will be consistent and not have "tearing". This is an improvement overall, but there may be applications that relied on the existing behavior.

This is the problematic code:

constructor(props) {
super(props);
const {
initializeStreamField, required, minNum, maxNum, icons, blockDefinitions,
value,
} = this.props;
initializeStreamField({
required, minNum, maxNum, icons, blockDefinitions,
isMobile: getIsMobile(),
value,
});
window.addEventListener('resize', this.onWindowResize);
}

The consequence is that BlocksContainer will fail to render because it does not expect to have access to an uninitialised state. It's generally not recommended to have side-effects in the constructor anyway, moving this init to componentDidMount would make the problem even more obvious.

I can see a few solutions:

  • Move the initializeStreamField logic out of StreamField, to be done when the store is created
  • Move initializeStreamField call to componentDidMount, and do not render the BlockContainer until initialisation is over.

Anyway, it's not necessary to upgrade to v6 now. I also have two concerns with the upgrade:

  • react-beautiful-dnd also uses Redux and react-redux v5, but doesn't declare them as peerDependencies. Using different versions from it would mean they get bundled twice for end users, which I would rather avoid. From memory Redux is fairly small in size, but react-redux is a good 20kb.
  • Wagtail uses v5, and switching to v6 will require updating Wagtail's code. Shouldn't be a big deal, but it will take a bit of time.

Finally on the react-redux front, I'm surprised that all/most of the components in the package are connected. I would expect the performance to be better if some of the connections were removed, as they clearly duplicate their computation (but use PureComponent or React.memo to still have the same rendering performance)

This would also make it easier to write tests for those components, which I would really like to see.

Smaller JS / React things

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