O que escolher como biblioteca de componentes para um projeto React

Meu nome é Ksyusha Lugovaya. Na SberCorus, estou apoiando a biblioteca de componentes Korus-UI React. 





Cedo ou tarde, quase todo desenvolvedor enfrenta o problema de escolher uma biblioteca e, às vezes, a solução pode não ser trivial. Surgem questões: o que orientar na escolha de uma biblioteca, quais soluções populares o mercado oferece, quais são seus prós e contras? Avaliações e depoimentos nem sempre ajudam a encontrar uma solução.





No mundo do desenvolvimento, não existe um ajuste perfeito para todas as situações. Portanto, no artigo irei lhe dizer como resolvemos este problema, e analisarei com exemplos de análise de várias soluções populares como escolher uma biblioteca de componentes React para seu projeto. 





Os principais critérios para a escolha de uma biblioteca

Cenários de uso da biblioteca. Isso parece óbvio, mas uma compreensão clara das tarefas é o principal critério de seleção.





Tipos de componentes de aplicativos. O tipo de aplicativo determina quais componentes você precisa. Freqüentemente, um conjunto de botões / caixas de seleção, campos de entrada básicos, listas / menus com estilos prontos são suficientes. Isso significa que você pode usar componentes simples com uma quantidade mínima de configurações e estilos prontos.





Personalização, formatação e interatividade no design. Se você precisa formatar e estilizar significativamente seus componentes, isso também é importante decidir com antecedência.





Quando os requisitos forem claramente declarados, responda às perguntas:





  • A documentação do projeto está bem escrita, existem exemplos interativos?





  • Quão ativamente o projeto é apoiado?





  • Quantos problemas existem no projeto e com que rapidez eles são resolvidos?





  • O projeto é gratuito ou licenciado comercialmente?





  • Os componentes são fáceis de personalizar?





  • O código da biblioteca é coberto por testes?





  • Quais navegadores e plataformas a biblioteca suporta?





Estas são perguntas universais para ajudá-lo a escolher uma biblioteca. Mesmo que a solução funcional seja ideal para as necessidades do seu projeto, a falta de suporte ou um grande número de bugs não resolvidos é um bom motivo para escolher outra biblioteca. 





, :





  • Material-UI,





  • Semantic-UI-React,





  • yandex-ui,





  • arui-feather,





  • Korus-UI.





,   – Material-UI Semantic-UI-React, .





– , (, ) , opensource .





.





— , .





.





Layout- 





, , , . :





  • ;





  • props.children;





  • ;





  • :  h1, section, div, span, Icon, Avatar.





- ,   . , Material-UI   Semantic-UI   . -   .





- (controls)





, , , , — , «»  . 





:





  • ;





  • props;





  • UI (disabled, required, isLoading).









, . 





:





  • ;





  • layout- (, , );





  • .













Layout





Controls





Modules









Material-UI





App Bar, Avatars, Badges, Bottom Navigation, Divider, Grid List, Lists, Paper, Progress, Snackbar, Tables, 





Button, Chip, Selection Controls, Text Fields, Pickers*





Dialog, Cards, Drawers, ExpansionPanel, Menu, Stepper, Tabs, Tooltip





26**





Semantic-UI-React





Container, Divider, Flag, Header, Icon, Image, Label, List, Loader, Placeholder, Rail, Reveal, Segment, Step, Breadcrumb, Form, Grid, Menu, Message, Table, Advertisement, Card, Comment, Feed, Item, Statistic





Button, Input, Checkbox, Radio, Select, Text Area





Accordion, Dimmer, Dropdown, Embed, Modal, Popup, Progress, Rating, Search, Sidebar, Sticky, Tab, Transition, Visibility, Confirm, Pagination, Portal, Ref, Transitionable Portal





52





yandex-ui





Badge, Divider, Icon, Image, Text, UserPic, ListTile, Spacer, Link, Spin





Attach, Button, Checkbox, Menu, Radiobox, RadioButton, Select, Slider, Textarea, Textinput, Tumbler





TabsMenu, Drawer, Dropdown, Messagebox, Modal, Popup, TabsPanes, Tooltip, Progress 





30





arui-feather





Amount, CardImage, FlagIcon, Form, GridRow, GridCol, Heading, Icon, InputGroup, Label, Link, List, Paragraph, Spin





Attach, Button, CardInput, CheckBoxGroup, CheckBox, FormField, IconButton, Input, RadioGroup, Radio, Select, TagButton, Textarea, Toggle





CalendatInput, Calendar, Collapse, EmailInput, InputAutocomplete, IntlPhoneInput, Menu, MoneyInput, Notification, PhoneInput, Plate, Popup, ProgressBar, Sidebar, SlideDown, Tabs





44





Korus-UI





HTML tags factory***,





Currency, Tags





Button, Checkbox, Input,  Radio, Rating, Slider, Switcher, Textarea





Autocomplete, ButtonGroup, Collapse, Collapsible, 





DatePicker, DateRange, DateTimePicker, DateTimeRange, Dropdown, DropdownLink, DropdownSelect, Dropzone, FileDrop, FileUpload, Loader, MaskedInput, Modal, MultiSelect, Notifications, NumericRange, NumericTextBox, Pagination, Password, ProgressBar, StatusBar, StickyPanel, Tabs, TimePicker, TimeRange, Tooltip, Tour,  Validation, VStepper, Wizard, form





45





+ - HTML-





*Material-UI





** ,





***Korus-UI HTML- c API





50% Material-UI Semantic-UI-React 30%   yandex-ui arui-feather — layout-.  Korus-UI 70% — .





. .





Material-UI





  • MuiThemeProvider. React .





  • . className.





classes.





CSS-in-Js, , CSS-. CSS-in-Js HOC withStyles() makeStyles() .





Semantic-UI-React





Semantic-UI-React ,   Semantic-UI.





, . 





:





  • , site.variables;





  • css- ;





  • theme.config;





  • assets .





yandex-ui





. .





:





  • themekit





  • () ;





  • - yaml json. (css, json, js, ios, android) .





arui-feather ( )





.  className, .





Korus-UI ()





  • LedaProvider. React .





  • .     API- (.  theme). . 





. , ,   ( Loader ).





.





Material-UI





component.





, List <ul>



. React :





<List component="nav">
  <ListItem button>
    <ListItemText primary="Trash" />
  </ListItem>
  <ListItem button>
    <ListItemText primary="Spam" />
  </ListItem>
</List>
      
      







Semantic-UI





Semantic-UI-React as:





<Button as='a' />
      
      



React- . .





yandex-ui





render-override.    . 





:





import React from 'react'
import { useRenderOverride } from '@yandex/ui/lib/render-override'

const ElementOriginal = ({ children }) => <div>{children}</div>
const MyComponent = ({ renderElement }) => {
  const Element = useRenderOverride(ElementOriginal, renderElement)
  return (
    <>
      <Element />
    </>
  )
}
      
      







yandex-ui  .





arui-feather ( )





.





Korus-UI





API.   Render. , , .





:





labelRender={() => <MyCustomLabel />}
      
      



:





({ Element, elementProps, componentProps, componentState }) => React.Node
      
      



  • Element



    -





  • elementProps



    - props





  • componentState



    , componentProps



    - props state





 





, , :





<L.CheckBox
  labelRender={({ elementProps }) => <MyCustomLabel {…elementProps} />}
>
  Label
</L.CheckBox>
      
      



React- 2 :





  • Typescript





  • PropTypes





React Typescript.   , . PropTypes —   .





Typescript.  Semantic-UI JS, Typescript Semantic-UI-React, React.





—  . , .   , .   .





, — . .





( ) ( ).





.









 









%





Material-UI





Chai, Mocha, Sinon





Unit





95.28% Statements





87.22% Branches





97.51% Functions





95.26% Lines





Semantic-UI





Jasmine, Karma





Unit









Semantic-UI-React





Chai, Enzyme





Unit









yandex-ui





Jest, Enzyme





Unit









arui-feather





Jest, Enzyme





Unit





88.1% Statements





73.84% Branches





66.61% Functions





87.19% Lines





Korus-UI





Cypress, Jest





Unit, end-to-end





69.28% Statements





56.14% Branches





66.29% Functions





71.78% Lines





, . Storybook .

















Storybook





Material-UI





https://material-ui.com/ru/





-





-





Semantic-UI-React





https://react.semantic-ui.com/





+





-





yandex-ui





https://yastatic.net/s3/frontend/lego/storybook/index.html





-





+





arui-feather





https://digital.alfabank.ru/





+





-





Korus-UI





https://opensource.esphere.ru/korus-ui/





+





+





, . , .





. , , , ,   . : , . 





-.    , .  , ,   .





Pulse GitHub Pull Request .   Insights . .





Material-UI





Semantic-UI





yandex-ui





 arui-feather ( )





 Korus-UI ()





GitHub   npm-. ,     .   . 





, — SEO-, .   , , Stackoverflow, Medium, DEV.   issues . 





,   , . .

















,  % 





Material-UI





63 400





6 372 353





0,99





Semantic-UI





48 800





541 299





9





Semantic-UI-React





11 900





8 620 967





0,14





@yandex/ui





212





15 902





1,33





arui-feather ( )





559





26 744





2









. . , , , . , . 





: . , . 





, , ( ). (-), .





.





:   . , , , «».





Korus-UI





const BasicForm = () => (
  <L.Div>
    <L.Input
      isRequired
      requiredMessage="Login is required"
      form="form"
      name="login"
      placeholder="Login"
    />
    <L.Input
      isRequired
      requiredMessage="Password is required"
      form="form"
      name="password"
      placeholder="Password"
    />
    <L.Button _warning form="form">
      Submit
    </L.Button>
  </L.Div>
);
      
      







Material-UI





const BasicForm = () => {
  const [login, setLogin] = React.useState("");
  const [loginError, setLoginError] = React.useState(false);
  const [password, setPassword] = React.useState("");
  const [passwordError, setPasswordError] = React.useState(false);

  return (
    <div>
      <form
        onSubmit={(e) => {
          e.preventDefault();
          setLoginError(!login);
          setPasswordError(!password);
        }}
      >
        <p>
          <TextField
            error={loginError}
            placeholder="Login"
            value={login}
            onChange={(e) => {
              setLoginError(false);
              setLogin(e.target.value);
            }}
            onBlur={(e) => {
              setLoginError(!login);
            }}
            helperText={loginError && "Login is required"}
          />
        </p>
        <p>
          <TextField
            error={passwordError}
            placeholder="Password"
            value={password}
            onChange={(e) => {
              setPasswordError(false);
              setPassword(e.target.value);
            }}
            onBlur={(e) => {
              setPasswordError(!password);
            }}
            helperText={passwordError && "Password is required"}
          />
        </p>
        <Button type="submit" color="primary" variant="contained">
          Sign Up
        </Button>
      </form>
    </div>
  );
};
      
      







Semantic-UI-React





const BasicForm = () => {
  const [login, setLogin] = React.useState("");
  const [loginError, setLoginError] = React.useState(false);
  const [password, setPassword] = React.useState("");
  const [passwordError, setPasswordError] = React.useState(false);

  return (
    <div>
      <Form
        onSubmit={(e) => {
          e.preventDefault();
          setLoginError(!login);
          setPasswordError(!password);
        }}
      >
        <Form.Group>
          <Form.Input
            error={loginError && { content: "Login is required" }}
            placeholder="Login"
            name="login"
            value={login}
            onChange={(e) => {
              setLoginError(false);
              setLogin(e.target.value);
            }}
            onBlur={(e) => {
              setLoginError(!login);
            }}
          />
          <Form.Input
            error={passwordError && { content: "Password is required" }}
            placeholder="password"
            name="password"
            value={password}
            onChange={(e) => {
              setPasswordError(false);
              setPassword(e.target.value);
            }}
            onBlur={(e) => {
              setPasswordError(!password);
            }}
          />
          <Form.Button content="Submit" />
        </Form.Group>
      </Form>
    </div>
  );
};
      
      







arui-feather





const BasicForm = () => {
  const [login, setLogin] = React.useState("");
  const [loginError, setLoginError] = React.useState(false);
  const [password, setPassword] = React.useState("");
  const [passwordError, setPasswordError] = React.useState(false);

  return (
    <Form
      onSubmit={(e) => {
        e.preventDefault();
        setLoginError(!login);
        setPasswordError(!password);
      }}
    >
      <FormField>
        <Input
          error={loginError && "Login is required"}
          placeholder="Login"
          value={login}
          onChange={(value) => {
            setLoginError(false);
            setLogin(value);
          }}
          onBlur={(e) => {
            setLoginError(!login);
          }}
        />
      </FormField>
      <FormField>
        <Input
          error={passwordError && "Password is required"}
          placeholder="Password"
          value={password}
          onChange={(value) => {
            setPasswordError(false);
            setPassword(value);
          }}
          onBlur={(e) => {
            setPasswordError(!password);
          }}
        />
      </FormField>
      <FormField>
        <Button view="extra" type="submit">
          Submit
        </Button>
      </FormField>
    </Form>
  );
};
      
      







yandex-ui





const BasicForm = () => {
  const [login, setLogin] = React.useState("");
  const [loginError, setLoginError] = React.useState(false);
  const [password, setPassword] = React.useState("");
  const [passwordError, setPasswordError] = React.useState(false);

  return (
    <form
      onSubmit={(e) => {
        e.preventDefault();
        setLoginError(!login);
        setPasswordError(!password);
      }}
      className={cnTheme(theme)}
    >
      <Textinput
        error={loginError}
        placeholder="Login"
        value={login}
        onChange={(e) => {
          setLoginError(false);
          setLogin(e.target.value);
        }}
        onBlur={(e) => {
          setLoginError(!login);
        }}
        hint={loginError && "Login is required"}
      />
      <Textinput
        error={loginError}
        placeholder="Password"
        value={password}
        onChange={(e) => {
          setPasswordError(false);
          setPassword(e.target.value);
        }}
        onBlur={(e) => {
          setPasswordError(!login);
        }}
        hint={passwordError && "Password is required"}
      />
      <Button type="submit" view="action">
        Submit
      </Button>
    </form>
  );
};
      
      







, Korus-UI , . 





Material-UI yandex-ui , Semantic-UI-React arui-feather <form>



.





, Korus-UI. .





React-

React-.









Korus-UI ()





Material-UI





Semantic-UI-React





arui-feather ( )





yandex-ui









Storybook





+

















+









+









+





+













Pull Request





70





241





2





0





0













MIT license





MIT license





MIT license





Mozilla Public License 2.0





Mozilla Public License 2.0









> 50%





+





+









+









E2E





+





















 





Chrome





85.0.4183.121





>= 49





Last 2 v.





Last 2 v.





Last 2 v.





Firefox





81.0.1





>= 52





Last 2 v.





Last 2 v.





>= 23





Edge





85.0.564.44





>=14





12+





Last 2 v.









IE





11





11





11+





11+





11+





Safari





14





>= 10





Last 2 v.





Last 2 v.









Opera













 





Last 2 v.





>= 12.1





Yandex













 





Last 2 v.





?





Android





 





 





4.4+





5+





>= 4





iOS Safari













7+





Last 2 v.





>= 5.1













+





+





+









+













+





+





+





















Typescript





Typescript





Typescript





Typescript





Typescript









GitHub , %









0,99





0,14





2





1,33













+









+





+













+





















. , .





, , .





Korus-UI

: ? React .





,   , . — , .





: , . . 





React-, . , .  , , .





Korus-UI 1,5 . opensource-. 





Korus-UI





Korus-UI : form, . , , . ,    L.form()



. , .





Korus-UI onValidationFail, , . — .





Korus-UI — . :





  • RegExp













  • ( )





  • isValid





  • unmounted





  • ,

















API





, _. css-:





<L.Div _flexBox> -> <div class="flex-box"></div>
      
      



className .





theme, css- .





Render (. ).





, :





{
  …Event, //  ,  React'
                
  //    component,     
  component: {
    isValid?: boolean, //   ,    onBlur
    name?: string, //  ,    
    value: any, //  
    … //    (. API )
  }
}
      
      



:





is: isOpen



, isValid



, isRequired



, isDisabled







has: hasCloseButton







should: shouldCorrectValue







ref



.





Korus-UI ref, React.





Korus-UI

, .   , issue   .





iOS Android. . .





React- Material-UI, Semantic-UI-React, arui-feather ( ), yandex-ui, Korus-UI (), . 





, : 





































Korus-UI, . , , Korus-UI .





. , Storybook.





  Korus-UI opensource GitHub. opensource, , :)





Também gostaria de expressar minha gratidão à equipe de desenvolvimento do SberCorus, o pai e inspirador ideológico da biblioteca, Artem Povolskikh . Se você estiver interessado em saber como o desenvolvimento de front-end funciona no SberCorus, leia o artigo de Artyom .





Compartilhe sua experiência com bibliotecas de componentes nos comentários. É interessante discutir quais vantagens e desvantagens você encontrou com a experiência pessoal e quais funcionalidades faltam no processo de trabalho. 








All Articles