Don't make learning React more difficult than it is
React itself has a quite small API surface to learn, and in theory, it should be easy to grasp. Unfortunately, the learning resources are making things look far more complex than it actually is. If learning React is a primary goal of the tutorial then every other library, tool or draft version of an ECMAScript language feature is just a distraction. Those might be useful later, but when you're showing how to create todo app then you're just making simple complex.
Let's start by looking how React novice will begin learning and where he/she will end up with current resources..
Down into the rabbit hole
The page that everyone reads when learning a new technology is the Getting Started page. React is not an exception. Getting Started page on an official React page introduces three ways to start experimenting with the technology. After picking easiest option without a package manager and build process, soon you have made a simple component, and you're eager to learn more.
While searching for tutorials, you start to encounter terms like Flux, functional programming, package management (even on getting started page) and immutability. When you research more you will notice that Flux is more like a pattern and that there are tens of Flux implementations. Then you might encounter Redux which has taken ideas from Flux (and Elm). While digging into Redux, you will eventually find yourself reading Immutable.js documentation as ECMAScript array manipulation functions mutate the array and avoiding mutation can be tricky. Soon you find yourself looking down into the rabbit hole.
Rabbit Hole - Metaphor for the conceptual path which is thought to lead to the true nature of reality. Infinitesimally deep and complex, venturing too far down is probably not that great of an idea. - Urban Dictionary
Straight to the "ideal" solution
I'll take React + Redux + react-redux as an example. Let's assume you're reading a tutorial that teaches you to create a todo app (or similarly sized project) step-by-step. At some point, there are instructions to do npm install redux react-redux
and add Provider
to your JSX.
import { Provider } from 'react-redux'
...
ReactDOM.render(
<Provider store={store}>
<App />
</Provider>,
targetEl
)
All this feels like a magic when you run the app. It works, but why and how? These questions will remain unanswered until you dig into the solution without that wonderful package. Authors of tutorials assume a lot, not only about React, but new language features also. For example in the source code above, you should know how ES6 feature destructuring assignment works.
Making the magic disappear
To get away from things happening magically, we need to understand what the 3rd party library is doing for us.
Back to the Provider
. The answer lies in the imported package and its source code. The Provider.js has 52 lines of code, and we should be able to understand what's going on.
It extends Component
and that's the reason we can wrap App
or any other component into it. It uses class
and extend
, but it's readable to a person who is not familiar with the ES2015.
export default class Provider extends Component {
Render function doesn't add anything else than children. It's a plain and simple wrapper element when it comes to rendering.
render() {
let { children } = this.props
return Children.only(children)
}
After skipping validation messages, constructor and data passing we're left with these lines:
getChildContext() {
return { store: this.store }
}
Provider.propTypes = {
store: storeShape.isRequired,
children: PropTypes.element.isRequired
}
Provider.childContextTypes = {
store: storeShape.isRequired
}
No one is calling getChildContext
, so it must be part of React. Searching for react context will give an official documentation about Context.
Occasionally, you want to pass data through the component tree without having to pass the props down manually at every level. React's "context" feature lets you do this.
That sounds good, without this we would have to pass store
as a property thought each child component:
<MyComponent
store={store}
>
Learning React
</MyComponent>
And MyComponent
would read it and pass it to it's children:
render() {
const props = this.props;
const { store } = props;
<MyChildComponent>
store={store}
</MyChildComponent>
Uh, get's tedious after a while.
If we wanted we could write our own "provider" using the react-redux source code as a guide:
class OurOwnProvider extends Component {
getChildContext() {
return {
store: this.props.store
};
}
render() {
let { children } = this.props
return Children.only(children)
}
}
OurOwnProvider.childContextTypes = {
store: React.PropTypes.object
};
I think we just cast a "dispel magic" spell and can now safely use react-redux (if we wanted). It's easy to forget that even a tiny library is still a dependency, and each dependency increases complexity. You might use TypeScript, and its type definitions don't match the latest version of react-redux, React API might change, and you would have to wait for next release of the library, etc.
For the tutorial authors
The kind folk who know a lot and want to spread the information should remember that readers haven't gone all the same hoops and loops as the author. The author might have been using the core technology long enough to appreciate provided convenience methods or higher abstraction.
Few things to remember while sharing information:
- do not use helper libraries unless you're teaching the usage of that library
- if you do use abstraction do it with reason and explain that reason
- make clear what are the prerequisites to get most out of the tutorial
- what is it exactly that you're teaching
- allow people to leave comments and make adjustments based on a feedback
- remember who is your audience
Choose material that suits your current level of understanding
If you're new to React, you should try to find learning material that solely focuses on one thing at a time. Do not aim for the ultimate solution. Iterate on the same exercise application and make better each round.
While reading React tutorials, you might have to learn ES2015/ES2016 syntax at the same time as most of the articles/tutorials use it. Learning essential language features is time well spent. You don't have to use those features immediately. You can write a more verbose version of a function first and make unit tests for it (or first tests and then code, if that's your cup of tea). Then you can safely rewrite the function with more expressive language features.
An example of focused learning material is Dan Abramov's Getting started with Redux at Egghead.io. He always shows you first how things are done "in the hard/verbose way" then step by step brings in helpers from packages.
When you have grasped the core then you can start reading more "complete app" tutorials/books/courses such as:
I will post more resources (people to follow, sites, etc.) on next blog post, so stay tuned.
What are your thoughts on learning things like React and what resources are you using?