Learning React - Why, Where, How?

  • Tutorial
Where to start learning a new library or framework? Immediately find an article on Habré and plunge headlong into the abyss of practical examples? Or first thoroughly study the official and unofficial documentation before moving on to practice? It is between these questions that your consciousness will rush about when you decide to find out what ReactJS is. So that the desire to learn does not die, like the famous donkey, be sure to look under the hood.

Prepare a sled in the summer and a cart in the winter


Few people think about how the finished application will work on a combat server. Typically, these issues are resolved at the very end, when the code is already written, and there is no turning back. That is why before starting to study the library itself, decide on the issues of compiling the code of your future creation. There are two options. For study, or, say, a demo of the site, the compilation option on the client side is suitable. You don’t have to do anything, the browser will do everything for you, on the fly, so to speak. But for the finished product, I would advise setting up server-side compilation. The benefit of tools for this abound. Here you and Babel , and NodeJS or Webpack .

Childhood, childhood, where did you go


Well, with the compilation issues sorted out. Let's move on to the study? No, it's too early. React implements a modular approach for building applications. What does it mean? Imagine a constructor. Not the constructor inside the class, but a simple children’s constructor. In the same way as you built your masterpieces from small blocks in childhood, you will build an application from React components. It’s even more interesting to play this way, since you yourself create the components too. The beauty of the modular approach is that by creating and testing such a component once, you can easily use it in your other applications. Therefore, my advice to you: create separate files for each of them, and then just connect where you want. It seems everything is simple, but it is not so. The application is empty, dead, if its components will not “communicate” with each other. And this is precisely the most difficult and interesting.

Well, let me work!


I see that your desire to learn is melting before our eyes. Therefore, we open the documentation and move from words to deeds. All that we need for study is on the official website of the library. True information is poorly structured. Helping you not to get lost in this chaos is the main task of this article.
As you already understood, the main task when developing applications on React is to break the page into blocks and create components that would implement the functionality of each of them.
To get started, create a “static” version of your component. I highly recommend paying attention to JSX .

var LoginForm = React.createClass({
render: function() {
        return (
                
) } }); React.render( , document.getElementById('example'));

Evaluate the benefits of JSX syntax? Then move on. Add some “interactivity.” The component’s interface will be redrawn automatically when any data inside this component changes. These include:

  • State - A set of data that reflects the state of a component at a particular point in time.
  • Props (properties) - data transmitted to the component through attributes.

Therefore, it comes down to a banal change in state or properties in response to user actions.

var LoginForm = React.createClass({
    getInitialState: function(){
        /* начальное состояние компонента */
        return { errorCode: 0, errorMessage: '', loginActions: [] };
    },
    doLogin: function(event) {
        event.preventDefault();
        var successLogin = (Math.random() >= 0.5) ? true : false;
        var actions = this.state.loginActions;
        if (!successLogin) {
            actions.push('Login failure');
            /* изменяем состояние компонента при возникновении ошибки */        
            this.setState({errorCode: 1, errorMessage: 'Error while login.', loginActions: actions});
        }
        else {
            actions.push('Login success');
            this.setState({errorCode: 0, errorMessage: '', loginActions: actions});
        }
    },
    render: function() {
        /* учитываем состояние компонента при отрисовке */
        var errorMessage = (this.state.errorCode > 0) ? this.state.errorMessage : '';
        var errorStyle = (this.state.errorCode > 0) ? {display: 'block'} : {display: 'none'};
        return (
            
{errorMessage}
/* передаем данные потомку через атрибут actions */
) } }); var ActionsList = React.createClass({ render: function() { /* данные, полученые от родителя доступны через this.props */ return (
    { this.props.actions.map(function(action) { return
  1. {action}
  2. ; }) }
) } }); React.render( , document.getElementById('example'));

As you already understood, React is significantly different from other libraries. Therefore, there is nothing surprising in the fact that when working with elements of the form, too, there are peculiarities that can add a fair amount of gray hair to your head. Form elements are divided into two types:

  • Uncontrolled - elements for which the value property is not set.
  • Controlled - elements in which the value property is set.

Let's set the initial value for input elements, and try to enter something:


As you can see, we did not succeed. Now React “controls” these elements and we need to write our own change handlers for them. Imagine how much work it is to write handler functions for each of the controlled elements? Mom do not cry! But the good uncles from Facebook did not leave us in trouble and added the ability to use mixins in React . Yes, and a few good additions (addons) tossed.

var LoginForm = React.createClass({
    /* подключаем примеси */
    mixins: [React.addons.LinkedStateMixin],
    getInitialState: function(){
        return { errorCode: 0, errorMessage: '', loginActions: [], defaultLogin: 'admin', defaultPassword: 'password' };
    },
    doLogin: function(event) {
        event.preventDefault();
        var successLogin = (Math.random() >= 0.5) ? true : false;
        var actions = this.state.loginActions;
        if (!successLogin) {
            actions.push('Login failure');
            this.setState({errorCode: 1, errorMessage: 'Error while login.', loginActions: actions});
        }
        else {
            actions.push('Login success');
            this.setState({errorCode: 0, errorMessage: '', loginActions: actions});
        }
    },
    render: function() {
        var errorMessage = (this.state.errorCode > 0) ? this.state.errorMessage : '';
        var errorStyle = (this.state.errorCode > 0) ? {display: 'block'} : {display: 'none'};
        return (
            
/* используем функцию из примеси и спецыальный атрибут valueLink */
{errorMessage}
) } }); var ActionsList = React.createClass({ render: function() { return (
    { this.props.actions.map(function(action) { return
  1. {action}
  2. ; }) }
) } }); React.render( , document.getElementById('example'));

If you think that there are no more “surprises”, then you are very mistaken. Here's the problem for you: how to organize bidirectional data exchange between components? After all, properties are transferred only in one direction - from father to descendants. And vice versa? How can a descendant influence their parent's data? Very simple:

var LoginForm = React.createClass({
    mixins: [React.addons.LinkedStateMixin],
    getInitialState: function(){
        /* мы хотим, чтобы потомок мог изменять состояние родителя, в часности, очищать масив loginActions */
        return { errorCode: 0, errorMessage: '', loginActions: [], defaultLogin: 'admin', defaultPassword: 'password' };
    },
    clearActionList: function() {
          /* для этого  в родителе создаем функцию, которая очищает loginActions */
          this.setState({loginActions: []});
    },
    doLogin: function(event) {
        event.preventDefault();
        var successLogin = (Math.random() >= 0.5) ? true : false;
        var actions = this.state.loginActions;
        if (!successLogin) {
            actions.push('Login failure');
            this.setState({errorCode: 1, errorMessage: 'Error while login.', loginActions: actions});
        }
        else {
            actions.push('Login success');
            this.setState({errorCode: 0, errorMessage: '', loginActions: actions});
        }
    },
    render: function() {
        var errorMessage = (this.state.errorCode > 0) ? this.state.errorMessage : '';
        var errorStyle = (this.state.errorCode > 0) ? {display: 'block'} : {display: 'none'};
        return (
            
{errorMessage}
/* и передаем эту функцию потомку через атрибут, точно так же, как и данные */
) } }); var ActionsList = React.createClass({ render: function() { return (
/* здесь мы можем изменять состояния родителя, вызывая соответствующую функцию - this.props.clearActions */
    { this.props.actions.map(function(action) { return
  1. {action}
  2. ; }) }
) } }); React.render( , document.getElementById('example'));

Cause time, fun hour!


Here you go. Now really everything. The first stage has been completed and I am pleased to welcome you in the ranks of the newly made reactors. Whether ReactJS is worth the time spent on it - everyone decides for himself. Only half way passed. For some, this road was easy, for someone - not very. Someone will go further, while someone will stop. And I really hope that my article will be a good help for beginners.

Also popular now: