Should the complex components of react be moved to library? - reactjs

I'm new to react development. I'm currently using Typescript for react with webpack and npm.
i'm working on a large scale project where components are complex. As of now they are kept in certain hierachy in project folder.
i recently learn about making components library. I'm thinking of taking complex components out of project and put them in a separate component library. However, other team members say it would cauae headache to maintain library separately. since there is less to no chance of using this in any other project (thats the current situation) they should not take the components out and maintain separately.
i want to know if that is the only reason the react developers create component and creating component to test it better and simplifing thw project complexity are not the valid reasons?

Related

Common React Components across multiple apps

We have 3 react apps. Some of the components being used in these apps are common for the 3 apps. We want to have a separate common git repo, where we can put the code for the common components and use those components in the 3 apps. Currently, we do have a repo for common components which is linked from the 3 apps like this in package.json:
package-name username/repo#commit-id
This arrangement poses some difficulties:
For some reason, hooks don't work in the common repo even if we upgrade the react version.
While developing locally, we change package.json to package-name ../path. Everytime we make a change locally in the common repo, the common repo has to be built again manually.
Overall, the process is not good. Many times it throws strange errors which are hard to solve.
Can you suggest an alternative way to accomplish the same?
For some reason, hooks don't work in the common repo even if we upgrade the react version.
Treat the component package as its own project. It should have its own package.json that declares its dependencies.
It sounds like you are trying to develop the component package at the same time you develop the other projects that use them. Instead, you should develop the component package in its own environment. If you find problems or think of new features to add to the component package while you work on a project that uses it, create new issues for the component package project and work on them there.
The projects that use this component package should declare a specific version (either by a tag or a commit) which they use. Upgrading to a new version of the component package should follow the same process as upgrading versions of a 3rd party package, such as React itself.

Can I use PreactJS with React Native using preact-compat (Or using any other method)?

I've been working with react and react native for a while and there's a library that caught my attention: Preact. I learned it (that being a react developer was not difficult), I did some PWA's to practice (Copying medium-sized projects that I've done in the past) and, if you know what Preact is, it goes without saying my impression. It seems incredible to me. My question is: is there a way to work with react native using Preact? Maybe with preact-compat?
Not out of the box, no. See this discussion from GitHub
The short answer is: use a native wrapper that exposes DOM.
The long answer is that there are woefully few options for this. Some time ago, I had begun building a DOM interface to React Native, but I have no experience with React Native whatsoever and I'm likely not the best person to do that implementation.
I do know that folks have used Preact with NativeScript and had some success: NativeScript doesn't expose a Web-compatible DOM, but its UI primitives are still quite easily mapped to DOM primitives:
https://github.com/staydecent/nativescript-preact
https://github.com/NathanaelA/nativescript-dom/blob/master/src/dom.js
It would also be relatively easy to implement a nativescript-preact using the source of nativescript-vue, which implements a simple DOM on top of NativeScript's UI components that Vue then renders to:
https://github.com/nativescript-vue/nativescript-vue/tree/master/platform/nativescript
It's also worth noting that preact-compat is the legacy package, used for Preact 8.x and prior. preact/compat is where you'd get compat going forward.

How to correctly handle PeerDependencies when working with a Components Libraries?

First of all, thank you for reading and trying to understand this question.
In my team we have built a library for common Components with React for about 2+ years. This library is built with Babel creating two different transpilations. One in CommonJS for our Test Runner to run tests (because Jest cannot use ESM) and another one in ESM for Create React App (Webpack inside) to make Tree Shaking possible. We use Create React App to build and develop our Apps.
This is working for us perfectly. But we have encounter a problem when managing Final Form Peer Dependencies (or any other library). This is our scenario:
Common Components Library
PeerDependencies
Final Form
DevDependencies
Final Form
App1
Dependencies
Common Components Library
Final Form
App2
Dependencies
Common Components Library
Final Form
App3 (It dont use FinalForm but it uses other Common Components)
Dependencies
Common Components Library
I'll explain this:
In our Common Components Library, which I spoke earlier, we have React Components that works with Final Form, like for example a Vitaminated Autocomplete Text Input Component that we share among many Apps. This Apps also use Final Form to create Components that implement forms locally for that App.
So App1 is right. Everything works fine. But for one thing, now if we want to upgrade Final Form version for this App because, lets say, we need a bug fix of Final Form. We are been forced to upgrade also our Common Components Library and the other App's Final Form version. We need to do this if we want to avoid execution errors within the Final Form React Context. If you are familiar with Final Form or React Context in general you probably have encountered this problem. You can't use different versions of a library that uses React Context. i.e: if we have final-form#1.2.3 in our Common Components Library and final-form#1.2.4 in our App1 it would genereate an execution error. So as I said, we are forced to upgrade not only on App1 and Common Component Library also on the other Apps that uses a Common Component on the Library that uses Final Form. The statement would be: 'Now, if we upgrade somewhere we have to upgrade everywhere'. And we don't want to do that. Probably we aren't handleling dependencies correctly.
So this drove us to move Final Form dependencies (we also use react-final-form, final-form-arrays, etc...) to PeerDependencies. Our problem was solved. But now, another one appeared when we saw that in Apps like App3 we were having an error when we build our App3 with Create React App. This is our output when using npm run build:
module not found `react-final-form' in file 'node_modules/CommonComponentsLibrary/VitaminatedAutoCompleteTextInput.js'
This means that, even with our App not using this VitaminatedAutoCompleteTextInput when we build its checking for every import in the node_modules so this is making us unable to build our App3. When we add the 'missing' depednencies to our App this builds with no problem and then when analyzing our bundle with source-map-explorer we see that final form depdenencies are not included in the bundle.
Is this necessary? I felt like we are missing something here. One solution for us has been including final form depdnencies on the Common Components Library as 'normal' dependencies but we were still having the first problem I mentioned before.
Maybe this problem is not only related with Create React App or Final Form. This is probably a more global isse within ESModules Libraries with Npm dependencies. Probably you will need me to enchance the explanation or have questions. I'll be glad to improve this question where needed. I have also searched on Google and here to find a similar question but I only found this. I dont know exactlcy if it's the same question but It have no answer yet.
Many thanks for trying to help or understand this issue,

lerna monorepo package structure

I am building a monorepo for a suite of React apps, and common library code. One of the packages would be a component library.
packages
app1
app2
common-ui
alert
button
I'm pretty new to the whole React/node ecosystem.
I've looked at a lot of actual UI library examples - react-bootstrap, material-design-components-react, etc.
It seems I would want to have each component in the common-ui lib to be distributed as single files, so that they can be cherry-picked when imported into a consuming app.
react-bootsrap does this by using babel to build the "lib". They build into a browser distributable, a commonjs lib, and an ES lib.
material-design-components-react does this by having their component lib itself by a lerna monorepo, with each component having its own package.json, and I believe they use webpack to build each component individually.
So my first question is,
Is a structure like material-design-components-react in my common-ui folder - kind of a monorepo within a monorepo possible?
Or would I have to restructure:
packages
app1
app2
alert
button
My second question is,
Which design is recommended by the community for a component library within a major monorepo? This must be a common structure developers have to solve when they have many client apps with common libraries. A package per common-ui component seems like a lot of overhead, but of course they have scripts to help out.
Is a structure like material-design-components-react in my common-ui
folder - kind of a monorepo within a monorepo possible?
Yes it's possible. But keep in mind, you and those libraries have very different requirements. You can think of your monorepo as small projects developed in same company., which are depending on similar 3rd party libraries and they follow same linting, testing etc.
Which design is recommended by the community for a component library
within a major monorepo? This must be a common structure developers
have to solve when they have many client apps with common libraries. A
package per common-ui component seems like a lot of overhead, but of
course they have scripts to help out.
First structure with 3 packages is most common way to start your repository/project.
In your case, I wouldn't recommend to divide your ux-library into single files. Your apps will likely use most of your ux-library and probably you won't have as much components as material or bootstrap has. Moreover, if you'd ever reach that point in your library, you can separate them later. For reference you can also check how lodash is publishing each of their functions. It's not different than your case (assuming you won't publish any fonts/images etc.).

React architecture for a huge business application

So we've recently picked up React in our company as the front-end technology to build our huge business web application. By saying recently, I mean we don't have any previous experience with React (we have a huge background of AngularJS), and by saying huge application, I mean it's really huge and very dynamic with lots and lots of different pieces and functionality.
Because we will have a lot of huge components that all play a very important role and have complex logic inside them, and because we want them to be easily pluggable and reusable, we want them to be as isolated as possible from the outside world and other parts of our application, because otherwise because of their size and complex functionality it would be pretty much impossible to develop and maintain them. That's the reason why we have decided NOT to use Redux, at least in the beginning, while we are developing just the separate components themselves, because it compromises component isolation and makes the whole application data flow logic impossible to understand when there are so many complex components. Although I believe our choice could be wrong, because as I've already mentioned, we have no experience with React.
As I've already mentioned, the application is very dynamic. By that I mean that components are actually rendered by data. We use various configuration provider classes that interacts with our API endpoints to get the pieces of our application's configuration, like configurations of navigation, pages, various forms, lists, etc., and then try to render components that are read from that configuration.
The problem is, after a couple of weeks struggling to get the momentum with React and discover the right patterns and common solutions to our problems, we've been talking in our crew, that maybe React is not the right technology for us, as it's a UI library, not event a framework, and it doesn't help us a lot, but just adds its rendering rules that we have to break at times to achieve the dynamics and component independence we want.
Considering the component isolation and data flow management, I personally have heard that there is a language for front-end development Elm that has pretty robust data flow architecture where each component has its own model that is separate from others, but I don't know whether it's worth a try, as it may fall behind our big requirements pretty soon too.
The reason I'm writing this question here is that I hope to get an insight from people that have a solid background on working with huge front-end applications. I'd like to know whether it's possible to develop such an application with React, whether React is suitable for such complexity and dynamics, whether we really need Redux or something else, what path, practices, ideologies should we follow. If you understood my question correctly, it's more the architecture side that we are struggling with, than the technological. Maybe we are just walking the path that leads to more and more struggle and complexity but not towards production.
There is absolutely no question that React/Redux can (and is widely) used to develop the kind of applications that you describe. Nothing in your description makes what you are building so unique that it excludes React as a platform for building it. We are actively working with a large enterprise customer who is building their entire front end - with 100 + SPA (Single page applications) in React. This is a team of over 100 developers over a 2-3 year project.
The way we structured this has been crucial -
First, you want to choose a UI component library. A few examples below :
MaterialUI - https://github.com/callemall/material-ui
React Strap - https://github.com/reactstrap/reactstrap
React Bootstrap -https://github.com/react-bootstrap/react-bootstrap
Khan Academy React Components https://github.com/Khan/react-components
https://github.com/elementalui/elemental
We basically took one of these and built a component library off of them, because our components are very custom styled.
Second, we created a modular architecture, where each module (SPA) is an npm package with a main container component and redux store.
Finally, we have a central server package, where each of the modules is registered. The server package is responsible for authentication, authorization, logging, routing, etc.
The essence of this answer is not to advise on how to structure a large React application, but to let you know that React can be (and is being) used to develop applications similar to what you are describing.
I'm at the similar situation right now. I have a background in large desktop applications (ERP, LOB - WinForms, WPF) - 1000+ modules, very dynamic (more than 70% of the UI was generated by input data/configuration), adding new functionality was just about extending some configuration (without touching source code).
I'm deeply investigating current web technologies and I'm more and more convinced that React is not a good fit for that. React really shines in small/middle size applications where you (and other team members) develop every page/component 'manually' (not dynamically generated) and you want to have one global state. But it doesn't help you with building large scale application out of the box - it is only UI library (so no support for modules, routing, forms, binding, http requests, static typing (typescript), etc.) and to my surprise, there is no support for style shadowing/encapsulation (you have to integrate, for example, CSS Modules, by your own). And at the end, you have to constantly bother with libraries versioning (to make them always work together is truly time and energy consuming).
I have a great experience with Angular 2/4+ and I think, for now, it is the best technology for that kind of the applications (if you know WPF, it is very similar). It is a full framework, which is prepared to the scaling out of the box. You can split your app into independent modules (specifying which components will be visible to the outside world), every component has public api (statically typed, inputs/outputs) and encapsulated css styles (there is no interference between others).
For the global state (logged in user, global configuration, etc.), you can still use library ngrx/store (which implements Redux pattern and comes with extra nice things, like 'effects' and integrates really well into Angular ecosystem).
I tried to do in Angular really crazy stuff (dynamically generating the whole application from backend configuration) and everything worked perfectly, as expected.
You nailed the issue in your question- react is a view library, not an application framework. The real question is whether React+Redux(or other state management system) is appropriate for a large LOB app.
I will share some insights from our team’s experience in this realm. Large LOB apps have been developed using the MVC/MVP/MVVM design patterns for decades. These are tried and true patterns that ship software. Couple that with dependency injection and you have a modularized, testable, maintainable application. AngularJS (2.0+) is founded on these principles and leverages them deeply. For this reason we use AngularJS for all of our enterprise line of business apps.
React on the other hand is a lightweight, spritely view render that is awesome for smaller applications and client facing pieces (for example taking a dynamic survey or a simple dashboard). We often turn to React and VueJS here because the full AngularJS stack is way overkill and too heavy.
Getting started writing more complex apps in React can really be a struggle, I know exactly how it feels!
As you say, React is a UI lib and not an event framework. That's why you typically need a library to handle events, for example Redux. You clearly state that you decided not to use Redux (you even used capital letters for not :) ). I would take a step back if I were you and reconsider that decision. You say the reason for not using Redux is that your cannot keep your components easily pluggable and reusable when using Redux. I would argue that is not true. Redux is totally decoupled from your React components. Redux only handles receiving events, and managing state. From the React components point of view, it just receives data in props and sends events by calling regular functions. It's possible to still unit-tests, reuse, etc.
I would suggest you take another look at Redux with this in consideration. Happy to help if you have more questions!
React , Redux will make things easier because When it comes to
complex applications you can create Well structured data object. then you can manage the Complete UI through React and its
Materials ... There are some reasons Why this is right choice
State Management ,
Tree Structure data handling,
Reduce the code,
You will be knowing where the changes made (Actions, Reducers)
Your Component will only taking care of UI things
The things that you have to do is Structuring your data
Completely understand your feelings when you start with React and Redux. We were in the same situation when we started with React in our company. At first React has different approach than other frameworks. Yes of course it's not framework, it's just library. You have to start thinking in React way and that is: React components just render state (It's like you render scene on your graphic card at first you have to prepare scene then you are able render), all what component can do is dispatch actions, or better call just action creators.
You need some smart way how to store state in that point I will suggest use Redux.
We also use TypeScript with combination React, Redux. you have to write more code than pure JS but static type control is priceless when you work on large project.
Separating components logic is native approach of react ... you have to separate logic write "Dummy components" and then reuse this with connect. Or passing values as props.
We are using Thunk middleware as action creators it's good because connected component will call just method and logic is in action creators. You have access there to whole state of app then you can fetch something and base on result you can dispatch different actions.
What I like on react/ redux is how to implement async calls etc. First design component to map all states
1) like I have no data
2) data loading
3) loading done
4) loading error
For that you need only one semaphore in you state and a few checks in render method. Then one action creator that will load data and base on progress dispatch action that describing progress.
What is also cool that in react/redux app you have single data flow it's good when new dev jump into project.
For UI we are using Material UI, yes this framework has some problems but nothing what you will not able to deal with.
We are using also Router for navigating in app.
In the beginning I will avoid server side rendering because it will much easier for you start just with client side rendering and with initial state.
When we start for us was useful this template where everything works in one project JavaScriptServices
Then off course great Abramov tutorials.
For design components very useful Storybook
We can write why use or not React for long time ... but What I can say ... for us it was good choice, with some pain in begging but now we have good payback.
We started a large scale business application using Reactjs as frontend technology.
We have over 30 people in the team and we have over 15 modules in our product.
My approach is to the project is developing a common react project that handles only the Authentication, authorization and routing of the application and all other components developed as separate npm react libraries.
To develop the libraries I used https://www.npmjs.com/package/create-react-hook
This library generates the template with an example app which can use to test our library.
Following is the structure of the project
--Library 1 ( Developed using create-react-hook )
--Library 2 ( Developed using create-react-hook )
...
--Library n
--Common Container App (Developed using create react app and have used all above libraries using npm install)
The main advantage of this approach is developers can focus only on their npm packages and they can develop and test relevant component(s) separately.
The deployment also becomes very easy because we can just update npm package of tested version and rebuild the container app and do the deployment without affecting any other part of the application.
We are using this for several months and running the project with a large team without any issue. I think this may be helpful to anyone else too.
So this is just to share my experience working on an enterprise react application that is in production for years in several banks. yes, you heard me right. Now you can imagine how huge the application will be if it's related to fintech (I know it's not always the case). we have huge modules (70+) with a complex logic that pretty much handles a lot of the work that a bank needs. Modules are both isolated and re-useable. I am going to give an example of only one module so you can imagine the size of each module.
Card Production Module
Bulk Card Generation
Bulk Card Export
Bulk Card Request
Card Operations
Card Operations Approvals
Card Printing
New Card Requests
Pin Generation
Pin Printing
This application is a product, not a project and as a product it is configurable. Even the UI is configurable. I have been working on this application as a full-stack developer. Since it's pretty old the state management library that we are using is flux. With state management, the development speed is a little slow but the tradeoffs are better with us not being worried about state management. By far the application has been able to handle huge changes and things which seemed unachievable. Stability has also been a key element throughout this period.
On the back-end, we have Restful services build using Dot Net which supports both MSSQL Server or Oracle depending on the client's needs/feasibility.
After countless react.js projects, I summarized a domain oriented and practical architecture in my blog post.
It is the absolute best practice that I applied many times, enjoy:
http://denislutz.com/domain-architecture-for-react

Resources