Ugh, the dependency injection stuff is just Angular all over again.
export default wire(Title, ['title'], function resolve(title) {
return { title };
});
Now I have to register "title" somewhere. Where is it registered? Did I remember to register it? I no longer know what's going on just by looking at the file in front of me, and my linter is silent. Then I have to annotate the function and declare it in the argument list. Items will be added and removed from the two lists as the app evolves, introducing more mental overhead and increased surface area for bugs, since once again my linter will have nothing to say on the topic.
Surely I'm in the minority given how popular Angular was, but I felt "DI" was the absolute worst thing about Angular's approach—basically a DSL layered over JS requiring yet more specialized tooling. The ability to look at just one file and understand it goes hand-in-hand with static analyzability, and I'd hate for the React community to abandon that and go down this path.
[edit] In the spirit of not dwelling on the negative, I should also say I did find most of the article to be a good summary of design patterns. Nice job!
Completely agree. I don't see many people in the React community advocating the use of DI though, so that's a plus.
The DI in Angular made a little bit of sense because JS modules weren't very widespread back then. But now, with ES6 imports (and/or 'require') there's no need. We have real modules now, and they can be dynamically injected for testing purposes with something like inject-loader[0].
I think Angular and/or DI's popularity has something to do with Java devs learning frontend development, and feeling more comfortable with more structure.
This is a misunderstanding of what Angular's DI is meant to solve - it is orthogonal to Angular 1's module system. DI is meant to solve runtime dependency management, which is a different problem from modularity, which is what ES6 modules are meant to solve.
For example, oftentimes one has a class that may have an instance floating around. One does not want to instantiate it unnecessarily if it already exists oftentimes, and so the injector will handle that automatically if necessary by instantiating an instance if it doesn't exist already, allowing for efficient memory management of services. It also has a major benefit for facilitating easier patterns for testing & readability.
Angular 1's DI has a poor API signature, with the naive allowance of it through a hacky regex, and crappy duplication of string references for the regular usage with minification taken into account - Angular 2's is built much more solidly and without such hacks.
It should also be noted that using cjs for dynamic injection is a bit of a hack as well, since it is a non-standard syntax. Angular 2's DI is much more pure, as it could be split off into a standalone library with some build configuration with zero external dependencies other than perhaps an ES6 shim like core.js.
Makes sense. My frustration in part stems from having worked on an app that used Angular DI and a module loading system (RequireJS) side by side. The conceptual dissonance and fallout between the two systems was an endless source of bickering and confusion for the team. I came to the situation having worked on a CommonJS/Browserify project, and it was like walking into a brick wall.
I worked on a project that had Angular + RequireJS too. I don't think having RequireJS added anything at all. It was just additional overhead - every module we added caused at least 3 files to change. We eventually ripped it out and just dealt with Angular's own module system.
Agreed, it serves no purpose. For testing, dynamic languages have the ability to ... dynamically replace dependencies. :) For building a library, a function that takes in dependencies and returns the component works extremely well & is straightforward to understand, no tooling required.
It's definitely not standard, the almost universal standard is using ES6 import/export. There are several other suspicious patterns here, I definitely wouldn't take these as canonical, or even best practices.
Yeah, I'm also not a fan of the DI example. I would rather explicitly pass it down the component tree or use Redux's connect. I believe React's docs advise against using context.
I don't mind DI, in Angular or elsewhere. I'm not sure in what way you think of it as a DSL, or even that it requires tooling. It's a useful pattern in OOP.
DI is fine, but that's just the concept that you ask for dependencies rather than relying on them.
foo(X dep) {}
vs
foo() {X dep = new X()}
It's overused imo but it's fine. The problem comes with DI frameworks like Spring or Angular DI when you start letting the framework tie your code together. This couples you tightly with the framework and can lead to odd situations where the thing you're getting isn't what you're expecting but that's not obvious because the object passing is happening behind a curtain.
DI is great; DI isn't the problem at all. It's rather the fact that Angular baked in a DI implementation that doesn't play well with either static analysis tools or module loaders. I'm not even criticizing the creators of Angular; they did something that made sense at the time and worked, in its way. It's just that Angular DI is icky and I hope to never have to deal with it again.
I started last week and got decently up to speed with these three articles:
[1] "ReactJS for Stupid People" - this explains what React is in simple meaningful terms.
[2] "React.js Introduction For People Who Know Just Enough jQuery To Get By" - this shows you how things are usually done with just jQuery compared to how it's done in React. It really allows you to see why the jQuery way sucks.
[3] "Flux For Stupid People" - by reading this you'll understand what the Flux stuff is about and can decide whether you need it or not - I chose to skip it.
Finally, if you want to get up to speed with ES6 classes at the same time, [4] shows you a simple example. I personally started writing my React stuff this way straight away.
I started with this tutorial[0] that covers react with no JSX, no Flux, no ES6, and no Webpack.
It is just a couple of script includes and normal html/javascript.
From that tutorial, I was able to understand exactly what react is. Then I started adding in the other items on top.
It's definitely not a boilerplate "site in 5 minutes", but it's also a lot less confusing when trying to learn what's going on underneath the hood with react.
This was my first exposure too. Once you're ready to build an app with JSX (probably right after you finish that tutorial and realize that typing React.createElement all over will get painful), check out the new tool Create React App[0] by Dan Abramov and the folks at Facebook. It's an official generator that'll get you going with no build to set up, and a bare minimum of necessary code, basically one step above Hello World.
I'm working on a book about learning React by itself, without Redux and Webpack and all the other tools that distract from learning the basics. Hope to have it out in the next week or so.
The links in the other replies are definitely good.
Beyond that, I maintain a big list of links to high-quality articles on React and related topics, at https://github.com/markerikson/react-redux-links . It's specifically intended to be a great place to start learning the ecosystem. Just for React, my list points to a couple dozen tutorial articles, a number of build-a-project tutorials, a number of articles that dig into how React works internally, and several paid courses and full books ( https://github.com/markerikson/react-redux-links/blob/master... ).
I am struggling a little with Flux, everyone has their own implementation of it. I mean that is grand, but what does it actually mean for me? Contextless.
When I was learning Flux I thought this video series[1] was really helpful. That being said, I've switched to Redux now and am much happier for it. If you're into videos I highly recommend Dan's (creator of Redux and on React core team) Egghead series[2].
I second that. Anything by Dan Abramov is worth your time. In addition to being a brilliant dev he's an excellent teacher. The egghead series is fantastic.
Don't implement Flux or Redux until you need it. This is what most React experts keep saying, but there are a ton of entry-level tutorials trying to teach both React concepts and Flux concepts (probably because it's a cool pattern). For most small apps, it's unnecessary. Pass state down as props.
If your component hierarchy matches your application state hierarchy, don't use flux. If you need to pass pieces of state around to a bunch of different components (like sharing state across views), use flux.
My first react application was complicated enough (enterprise analytics application) to require a flux implementation. I went redux and would highly recommend it both due to its ease-of-use and popularity. However, in subsequent applications I haven't needed it and have enjoyed writing vanilla react.
But also recognize when you'll need it, before you need it. I'm working on a React Native application without Flux, and it's turned into a massive roadblock because there's no concept of unidirectional data flow. Passing state up, down, and trying to sync it between components has become a mess and has lead to very tightly coupled components.
Honestly, people are just settling on redux. It builds on flux and really is pretty easy to use. Is it the best solution? No idea, but it works and it's quickly becoming the de facto implementation.
This comment is sure to prove controversial among the more rigorous React followers, but i disagree with the anti-pattern claims. Having built a startup on Backbone and React, i find that referencing `this.state` is a fine way to handle data shifts in our views.
While i have read the oft-presented reasons for not using `this.state`, the arguments feel more academic to me than being based in practical examples. Your milage may vary, but in my experiences `this.state` is one of the more powerful features in React. To me, removing read access to component state also removes one of the more compelling reasons to include React into your codebase at all.
To be clear, I wasn't meaning that use of local state was an anti-pattern in itself. I only meant that dumping all of the state of a wrapper component into the child should be avoided. Ideally, the complexity of the data in the props of a component should lessen the closer one gets to a leaf in the view tree.
Yep, using something like Redux or MobX absolutely does not mean "no React component state ever". There's definitely use cases for all of the above. Dan Abramov has tried to make that point repeatedly, and I made sure to put that viewpoint into the Redux FAQ ( http://redux.js.org/docs/FAQ.html#organizing-state-only-redu... ).
There are some legitimate reasons to use state, and I would argue that an HOC is legitimately one of them. (In fact fundamentally that is what redux's connect function really is)
One thing I prefer about Angular is all of these patterns are established and documented by the same people who designed the framework. In React they are distributed among hundreds of blogs and individual github repos, which all debate each other.
How long has React been out? Simple patterns such as component communication are debated, and third-party documentation about them is newsworthy?
The patterns handed down by the authors of Angular were one team's idea of how to do things, at a specific moment in time, which subsequently got enshrined and frozen in place for everyone for the next several years. And it works! It's a legitimate way to run a framework.
But, in such an environment, there's no marketplace where ideas can compete and evolve. There's a trade-off where you have to do the hard work of navigating and choosing among competing ideas, but the benefit of React is that you can choose an architecture, today, that isn't a four-year-old snapshot of a small group's idiosyncratic architectural preferences.
I think this is great advice for a beginner on their first project. Using React's localState for everything is a huge anti-pattern, but Redux adds cognitive overhead and boilerplate.
Later, when you do a real project, Redux makes debugging and state consistency about 10 times easier, especially on a team or coordinating between multiple teams.
I find a mix is good. I went without a flux implementation for a while and eventually ran into issues with figuring out what components to implement business logic and typical action reducer type work.
I'd say really good advice I wish I had known was don't start with a flux implementation. Build out your app with standard react state, use state only at last cost (ie derive logic off of props or whatever else via functions before storing state data), and only when you get into a bit of mess with a really large application and too much difficulty deciphering what components are providing logic and how they interact with each other should you implement a flux.
Also, it's worth watching Dan Abramov's learning redux course on egghead just for how it gets you to think about react, javascript, and GUI development in general.
Surely I'm in the minority given how popular Angular was, but I felt "DI" was the absolute worst thing about Angular's approach—basically a DSL layered over JS requiring yet more specialized tooling. The ability to look at just one file and understand it goes hand-in-hand with static analyzability, and I'd hate for the React community to abandon that and go down this path.
[edit] In the spirit of not dwelling on the negative, I should also say I did find most of the article to be a good summary of design patterns. Nice job!