⬆️ ⬇️

Why I switched from React to Cycle.js



It is not hard to guess that most developers are now using any frameworks to develop applications. They help us structure complex applications and save time. Every day one can observe a large number of discussions, which framework is better, which one should be taught, and so on. So, this time I will share my experience and answer the question: “Why did I switch to Cycle.js from React?”.



React is perhaps the most popular frontend framework (at the time of 2017) with a huge community. I am a big fan of this framework and it helped me to change the view on web applications and their development. Some love him, and someone thinks he's not so good.



Most use React without thinking that there is a better tool or method for developing web applications. This gave me an impetus to try Cycle.js, as a new reactive framework, which is becoming more and more popular day by day.



And in this article I want to explain:



  1. What is reactive programming
  2. How does Cycle.js work
  3. And why is he, in my opinion, better than React


What is reactive programming?



Reactive programming (RP, RP) is the work with asynchronous data streams. If you created a web application, you may have already written a lot of reactive code. As an example, a click event is an asynchronous data stream. We can monitor it and create side effects . The idea of ​​reactive programming is to give the ability to create data streams anywhere and work with them. Then we can create some abstractions for all side effects, which are much easier to use, maintain and test.



You may ask the question: “Why do I need this new“ reactive ”approach to programming?”. The answer is simple: Reactive programming helps unify the code and makes it more consistent. No more thinking about how something should work and how to implement it correctly. Just write the code in a certain way, without worrying with what data we work (mouse clicks, http requests, web sockets). All of this is data streams, and each stream has many methods that allow you to work with this data, for example map or filter . These functions return new threads that can also be used.

')

Reactive programming provides abstractions, and this makes it possible to concentrate on business logic.







Reactive JavaScript Programming



There are a couple of great libraries for working with data streams in Javascript. One of them is the well-known Rx-JS extension ReactiveX, an API for asynchronous programming with monitored data streams. You can create an Observable (data stream) and manage it with a variety of functions.



The second library is Most.js. It has better performance, as evidenced by tests .



Also worth noting is one small and fast xstream library written by the author Cycle.js. It contains 26 methods and weighs 30kb. This is one of the fastest libraries for reactive programming on JS.



Just the examples for this article use the xstream library. Cycle.js was created to be small frameworks and I want to use the lightweight library together with Cycle.js.



What is Cycle.js?



Cycle.js is a functional and reactive Javascript framework. It provides abstractions for applications in the form of a pure main() function . In functional programming, functions must take parameters as input and return something without side effects. In Cycle.js, the main() function accepts parameters from the outside world and writes it to the outside world too. Side effects are realized with the help of drivers. Drivers are plugins that control DOM, HTTP requests, web sockets, and so on.





Cycle.js helps you create a user interface, test it, and write reusable code. Each component is a pure feature that can run independently.



The main API has only one function, run() with two arguments:



 run(app, drivers); 


app is the main clean function, and drivers are the above drivers.



The functionality of Cycle.js is divided into several small modules:





Cycle.js code



Want to see some Cycle.js code? We will create a simple application that demonstrates how it all works. It seems to me that the good old counter application would be ideal for this example. We will see how to work with DOM events and re-rendering DOM elements.



Let's create two files: index.html and main.js index.html will contain only the main file with scripts, where all the logic is registered.



npm install and continue configuration
First you need to create a new package.json , so we’ll run



 npm init -y 


Then install the main dependencies



 npm install @cycle/dom @cycle/run xstream --save 


This command will put @cycle/dom , @cycle/xstream-run , and xstream . We also need babel , browserify and mkdirp , install them:



 npm install babel-cli babel-preset-es2015 babel-register babelify browserify mkdirp --save-dev 


To work with Babel, create a .babelrc file in the root of the directory with the following contents:



 { "presets": ["es2015"] } 


We also need to add scripts that simplify the launch of commands in package.json



 "scripts": { "prebrowserify": "mkdirp dist", "browserify": "browserify main.js -t babelify --outfile dist/main.js", "start": "npm install && npm run browserify && echo 'OPEN index.html IN YOUR BROWSER'" } 


To run our Cycle.js application, you need to run the command



 npm run start 


Everything. Installation is complete, now we can start writing code.



Start by adding a little HTML code inside index.html



index.html
 < !DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"/> <title>Cycle.js counter</title> </head> <body> <div id="main"></div> <script src="./dist/main.js"></script> </body> </html> 




We created a div with the main identifier. Cycle.js will contact this element and render the entire application into it. We also included a dist/main.js file. This is a jas-file transported through the babel, which will be created from the main.js file.



Time to write some Cycle.js code. Open main.js and import all necessary dependencies:



 import xs from 'xstream'; import { run } from '@cycle/run'; import { div, button, p, makeDOMDriver } from '@cycle/dom'; 


We included xstream , run , makeDOMDriver and functions that will help us work with Virtual DOM ( div , button and p ).



Let's write the main main function:



 function main(sources) { const action$ = xs.merge( sources.DOM.select('.decrement').events('click').map(ev => -1), sources.DOM.select('.increment').events('click').map(ev => +1) ); const count$ = action$.fold((acc, x) => acc + x, 0); const vdom$ = count$.map(count => div([ button('.decrement', 'Decrement'), button('.increment', 'Increment'), p('Counter: ' + count) ]) ); return { DOM: vdom$, }; } run(main, { DOM: makeDOMDriver('#main') }); 


This is our main main function. It takes the input parameters and returns the result. Input parameters are DOM streams (DOM streams), and the result is Virtual DOM. Let's start the explanation step by step:



 const action$ = xs.merge( sources.DOM.select('.decrement').events('click').map(ev => -1), sources.DOM.select('.increment').events('click').map(ev => +1) ); 


Here we merge two streams into one stream, called action$ (here we use the "$" suffix convention for those variables that represent the data stream). One of the streams is a click on the button ( .decrement ) decrementing the counter by one, the second - on the other, increasing the counter, the button ( .increment ). We associate these events with the numbers -1 and +1 , respectively. At the end of the merge, the action$ flow will be as follows:



 ----(-1)-----(+1)------(-1)------(-1)------ 


Create another stream count$



 const count$ = action$.fold((acc, x) => acc + x, 0); 


The fold function is perfect for this purpose. It takes two arguments: accumulate and seed . seed is first emitted until the event comes. The next event is combined with the first, based on the accumulate functions. This is practically a reduce() function reduce() for threads.



Our count$ stream gets 0 as the initial value, then for each new value from the action$ stream, we add up with the current value of the count$ stream.



At the very end, completing the cycle of the function, you need to run the run function under the main .



The final step is to create a Virtual DOM:



 const vdom$ = count$.map(count => div([ button('.decrement', 'Decrement'), button('.increment', 'Increment'), p('Counter: ' + count) ]) ); 


We map the data in the count$ stream and return the Virtual DOM for each item in the stream. Virtual DOM contains one div wrapper, two buttons, and a paragraph. As you can see, Cycle.js works with the DOM using the JS functions, but JSX can also be used .



At the end of the main function, we need to return our Virtual DOM:



 return { DOM: vdom$, }; 


We pass the main function and the DOM driver that is connected to and get the event flow for this div element. We complete our cycle and create a great Cycle.js application.



Here's how it works:





That's all! This way you can work with DOM threads. If you want to see how to work with HTTP streams in Cycle.js, I wrote an article [eng] about it.



All code can be found on the GitHub repository .



Why did I switch from React to Cycle.js?



Now you understand the basic principles of reactive programming and have already seen a simple example on Cycle.js, so let's talk about why I will use this bundle for my next project.



When developing web applications, managing a huge amount of code and data from various sources is a big problem. I am a React fan and I had many projects, but React did not solve all my problems.



React performed well when it came to rendering small data and changing the state of an application. In fact, its component methodology is awesome and really helps to write high-quality, supported and tested code. But all the time something was missing.



Let's look at the pros and cons of using Cycle.js instead of React.



pros



1. Large code base



When the application becomes large, problems arise when using React. Imagine that we have 100 components inside 100 containers, and each of them has its own functionality, tests and styles. This is a lot of lines of code inside multiple files inside a heap of directories. In this case, it is difficult to switch between all these files.



2. Data Flows



For me, the biggest problem React is the data flow. React was not originally designed to work with data streams, and this is not in the React core. The developers tried to solve this, and we have a lot of libraries and methodologies that solve this problem. The most popular is Redux. But he is not perfect. You need to spend a lot of time to configure it and you need to write a lot of code, which allows you to simply work with data streams.



With Cycle.js, another story, the creator wanted to make the framework such that it initially worked with data streams, so you don’t need to think about this implementation. All you need is to write functions that operate on the data and Cycle.js will take care of the rest.



3. Side effects of functions



React has some problems with side effects. There is no standardized approach to working with side effects in React applications. There are many tools that help to work, but it also takes time to install and study them. The most popular are redux-saga, redux-effects, redux-side-effects, and redux-loop. See what I mean? There are many of them. And you need to choose what to teach and what to implement in your project.



4. Functional programming



The creators of React argue that React uses a functional approach to programming, but this is not entirely true. There are many OOP classes, the use of this , which causes a headache if something goes wrong.



Cycle.js is built on a functional paradigm. Everything in it is a function that does not depend on the external state. There are not even classes. It is much easier to test and maintain.



Minuses



1. Community



Currently, React is the most popular framework and is used everywhere. Cycle.js - no. It is still not very popular, and it will be a problem when you encounter a problem, and finding a solution online will not be so easy. At times there is no solution to the problem, and you will have to solve it yourself.



This is not a problem when you are working on your project and you have a lot of free time. But what will happen if you work in a company and you have a deadline on your nose? You will spend a lot of time debugging your code.



But it is changing. Many developers start to use Cycke.js and talk about it, about the problems. Solve them together. Cycle.js also has good documentation with many examples. I did not have such difficult mistakes that were difficult to debug.



2. Exploring the new approach



Reactive programming is different from normal and you need to spend some time first to understand how to work. As a result, it will be easy, but if you have a quick deadline, then learning a new approach will be a problem.



3. Some applications do not need a reactive approach.



Yes, some applications should not be "reactive." Blocks selling sites, landing pages and many other static sites with limited functionality do not need a reactive approach. There is no data that passes through the entire application in real time, there are not so many forms and buttons. Using a reactive framework, you may make such sites slower. You need to understand when an application needs Cycle.js and a reactive approach, and when it doesn't.



Conclusion



The ideal framework should help focus on building functionality, and should not force writing template code. It seems to me that Cycle.js shows that this is really possible and gives impetus to the search for the best approaches to writing code and creating functionality. But we must remember that there is nothing perfect and there is always room for improvement.



Have you tried reactive programming or Cycle.js? Have I convinced you to try? Let me know what you think in the comments like, subscribe to ... !

Source: https://habr.com/ru/post/332674/



All Articles