206 karma · joined February 25, 2013
From a cyclist’s perspective, this is fundamentally a stopgap product for “curious” customers dipping their toes into e-bikes. I don’t say that necessarily to criticize it. There’s a place for a product that someone can put on any old bike and see if they want to buy a more expensive long-term solution. But that doesn’t make it a product I’d recommend.
The tire wear problem is significant enough that there are heat resistant tires specifically for this type of drum application (designed for old-style indoor trainers, not for use on the road), because use on a drum will cause premature wear for normal road tires.
Independent of what humans may do with the same prompt, training datasets will be full of traditional bike photos, which will all be drive side.
It’s also one of the easiest yellow flags to look for in used bike listings (not low-end, but anything enthusiast level). If a bike is photographed on the wrong side, there’s a non-negligible chance it’s stolen, because the seller is presumed to know better if they’re an enthusiast themself.
If you have only tried first-gen MIPS, I recommend giving it another shot.
The browser enforces the same-origin policy by preventing read on non-mutating (i.e. “simple”) request responses and preventing sending of mutating requests (i.e. non-“simple”). CORS provides a protocol for a service to loosen these controls.
It is a vector for script injection, and should be disallowed with a strong CSP (no “unsafe-inline”).
To ride out of the door zone in many cases requires taking the lane and riding outside of a marked bicycle lane, if present. Cyclists can and should do this, but it is no surprise that many don’t, and it is no surprise that drivers complain of those who do.
---
As I understand the interface, practical use of the EventListener interface boils down to the implementer performing a form of event delegation, where you'd wind up delegating from a single `handleEvent()` method on a class to handle different event types and/or events with different target elements -- as opposed to a single click handler in a simple button click example. I'd love to understand and quantify the benefit of this. If it's a significant improvement, it'd be doubly unfortunate, as many callback-based interfaces in JavaScript APIs and libraries at a higher level don't support such a model.
Assuming there's a strong benefit, I also wonder if there's an opportunity for build-time tooling to rewrite code from ad-hoc callbacks to more efficient delegation along these lines. Tangentially, I also don't know about `Function.prototype.bind` vs wrapping arrow functions in terms of performance; that's also something I'm curious about, as they're often a 1:1 analog.
I'm tempted to test a few of these things out myself, but if you have references, that would be helpful.
Take the following example, which is a normal class method:
> alertSum() { alert(this.a + this.b); }
And here we have an arrow function used to create an instance method (just an arrow function assigned to a property on the instance):
> alertSum = () => { alert(this.a + this.b); }
Then let's say we want to pass the method directly as callback:
> this.button.addEventListener('click', this.alertSum)
The first example (class method syntax) won't have the necessary `this` context unless it has its context bound to the instance through `Function.prototype.bind`. There are other patterns to avoid this (e.g. wrapping all callbacks in arrow functions when passing them), but it's useful to consider that classes methods can easily create confusion because that's _exactly where_ someone more used to a different language may assume the `this` context is bound lexically.
1. Is there a substantial technical or organizational change your company/org/team is currently executing? (Choosing scope based on who you're talking to.)
2. (If not) What was the last one you executed successfully? (Alternative: unsuccessfully)
3. What problem is/was this change aiming to solve?
4. Did the change introduce an anticipated or unanticipated tradeoff?
The goal would be to understand what the company currently or recently found challenging and what they're motivated to solve. It can also gauge the company's realism in evaluating the outcome.
Can you acknowledge real problems and tradeoffs, drive a change, and know when it's accomplished (or when it's time to rethink it)?
Now, there are tradeoffs we can make to deliver an end state to a user: we can normalize and incrementally hydrate the data shown in the client and increase visible jank in the process, or we can realign the app's experience and/or data source around each other.
Decoupling UI components from business components is of course valuable, but that's different from taking that a step further and decoupling business components from the data source. The latter is a significantly more challenging proposition.
Also, there's some fuzziness here in what we mean by decouple. REST vs SOAP vs GraphQL as transfer layers can be abstracted away as implementation details, but I'd place a higher emphasis on the shape of the data and how it has to be traversed in the client. If you have a paginated list, for example, and you only want to load it once, but you need to display both a summary and load it incrementally, things can get complicated as more functionality is built out from that starting point, regardless of transfer layer.
// Given:
const fooPromise = asyncFoo();
const barPromise = asyncBar();
// Then this...
await fooPromise;
await barPromise;
// ...is equivalent to this:
await Promise.all([fooPromise, barPromise]);
Now, Promise.all() is useful, but it is unrelated to when computation starts.At the same time, unless I'm really misunderstanding the example you shared, I can't see the problem or mental overhead you're mentioning where we need to be vigilant about having the same hook used in multiple places or understanding the scope of the hook's "local" state and callbacks. That's the point of hooks as a unit of encapsulation -- just like with a class, each use of a hook is a different instance, and the scope is that of the instance (and hook instances are scoped/bound to the lifecycle of the containing component instance). The code in the problem you showed is equivalent to calling setState on the one component instance and expecting that to show up on another instance which happens to be of the same component class. If we understand how React component instances work, that's clearly not the case (state isn't broadcast across instances), and the same goes for hooks.
Looking at what I mean by the improved portabiliy/hoistability of hooks I mentioned in previous comments, let's say we have three components: App, Foo, and Bar. App renders Foo and Bar as children.
We have a business requirement that Foo has some behavior which contains multiple pieces of state and bindings to multiple React lifecycle events (e.g. mount). What we don't know is whether we'll ever need to share that behavior with Bar.
React class API: We need to write bindings for this behavior against class state and lifecycle methods, intermingled with other code. This intermingling means you know there's a good deal of refactoring to do to move the behavior upward to App if we ever need to share the behavior with Bar. As a component grows, more and more logic intermingles on those lifecycle methods and makes refactoring more challenging.
class Foo extends React.Component {
state: {
behaviorState: {...},
unrelatedState: {...},
};
componentDidMount() {
initBehavior(this.props.input);
initUnrelated();
}
...
}
React hook API: We can easily write this behavior in a custom hook, encapsulating the behavior in some combination of useState, useEffect, and other React hooks. Now we have a self-contained useBehavior hook, by definition isolated from any local state, which you can choose to use within Foo. const Foo = ({ input }) => {
const behaviorState = useBehavior(input);
const unrelatedState = useUnrelated();
return ...;
};
At this point, we're not so worried if we need to hoist that one function call up to App and pass the hook's returned handle (behaviorState) back down to Foo and Bar at some point in the future.If this example sounds trivial, I've packaged up 500+ lines of functionality in a single self-contained hook before, and that's all exposed as a single function that consumers can treat as a full encapsulation of all of that functionality, while not worrying if they need to hoist that function call up and pass the output down at some point in the future.
I'm not talking about calling the same hook in Foo and Bar (these are different instances), nor sharing local state sideways across different invocations of hooks, but rather having full confidence it won't be hard to re-anchor that hook upward in the component tree if need be.
And I'd like to be very clear that I strongly advise against cutting through layers with context because I wholeheartedly agree with your assessment there. You can plumb down those handles explicitly through props and enforce they're provided in a type system.
I believe this model has similarities to both Apollo and Angular services, though I don't have direct experience with either.
Render props and HoCs solve similar problems for composition/reuse of functionality (these are all mixins at heart), but the hoistability of hooks is really the distinguishing mark in my experience.
* Edit: The header image failed to load for me and complicates much of what I said in the following paragraph; it isn't as cut and dry as it first appeared.
First off, that automated WAVE report is stellar for GetCalFresh. The color contrast here is an excellent example of strict conformance to WCAG 2.0 AA contrast requirements. (Most of the site is hitting AAA contrast requirements, which is above and beyond.) The report identifies a issue for an image element's contrast in the footer. Please note that this is a false positive; the actual visual contrast meets the requirement.
Heading levels are always a bit of a mess as projects get larger, but as the linked report shows, they could easily be improved slightly in this case. That's not going to outright break the site or render it inaccessible; however, it is a slightly less navigable experience for a user.
Finally, it's important to look at both the spirit and practice of conformance to accessibility standards. In spirit, these are usability standards. You can build something that checks all the automatically enforceable, auditable boxes in the standards, but is unusable in practice. Or you can focus on delivering a strong experience to users, focusing on the POUR principles, and I'd argue that's what an accessible experience should look like (not to exclude ensuring the more baseline elements of conformance, of course).
The concern the BEM and component-based CSS approaches aim to address is the composition of arbitrary chunks of DOM without implicit side effects. By having chunks of DOM explicitly opt in via classes to being styled in a given way, they never accidentally receive styles they weren't meant to, and they're fully portable to arbitrary contexts.
In something like an web application as opposed to a document-oriented website, the ability to compose components and avoid quirks of things that randomly break or look different inside other things is beneficial. Using a component in a new place shouldn't (in the application development context) require adding new selectors for it because it's not "where" your selectors expected it to be.
It's fair to point out that the browser feature is not widely used, but when it is used, it's likely by users who benefit most from the small amount of effort it takes to support it. (It's really a few lines of CSS, plus simply using rems as your websites unit whenever you'd otherwise use px. It's even easier in terms of avoiding weird 16px-based rem calculations if you make your rems 10px for a default 16px browser preference by applying a straightforward conversion on the root element.)