• Redux и MobX - плюсы и минусы, когда лучше что использовать?

    vahe_2000
    @vahe_2000
    4 причины использовать MobX
    1. 1 Легко научиться и использовать
    2. Меньше кода писать
    3. Полная поддержка объектно-ориентированного программирования
    4. Работе с вложенными данными легко
    2 Причины не использовать MobX
    1. Слишком много свободы
    2. Трудно отлаживать


    Я использую MobX сейчас, потому что я могу писать код в 3 раза быстрее, чем с Redux.

    Редукс в значительной степени зависит от принципов функционального программирования:
    На мобкс влияет объектно-ориентированное программирование и принципы реактивного программирования:
    Ответ написан
    Комментировать
  • Чем заменить функцию .map() в моем случае?

    @askhat
    На вопрос ответил автор вопроса, я в свою очередь попытаюсь объяснить что произошло.

    Рендер в реакте всегда идёт по наименее трудозатратному пути, а именно вычисляет дельту (разницу) между новым стейтом и предыдущим, если таковой имеется. Например:

    class TodoList extends React.Component {
      state = {
        todos: [
          'Commit',
          'Push'
        ]
      }
      render() {
        return <ul>
          {this.state.todos.map(item => {
            return <li>{ todo }</li>
          }
        </ul>
      }
    }


    Если стейт компонента изменится, скажем при добавление элемента в начало списка todos, так что он станет таким:

    const todos = [
      'Init',
      'Commit',
      'Push'
    ]


    Реакт вычислит два древа VirtualDOM:

    // Начальный стейт
    <ul>
      <li>Commit</li>
      <li>Push</li>
    </ul>
    // Добавлен элемент
    <ul>
      <li>Init</li> // <- разница начинается здесь и до конца древа
      <li>Commit</li>
      <li>Push</li>
    </ul>


    Здесь выполняется работа которой можно было бы избежать. К примеру если бы элемент был добавлен в конец списка:

    const todos = [
      'Commit',
      'Push',
      'Merge'
    ]


    То реакт получил бы на сравнение другие два древа элементов:

    // Начальный стейт
    <ul>
      <li>Commit</li>
      <li>Push</li>
    </ul>
    // Добавлен элемент
    <ul>
      <li>Commit</li>
      <li>Push</li>
      <li>Merge</li> <- разница начинается здесь, от начала и до сих по ничего не менялось
    </ul>


    Дельта этих двух списков меньше, а значит и работы нужно сделать меньше.

    Совершенно очевидно что <li>Commit</li> и <li>Push</li> не менялись, однако реакт недостаточно умён чтобы это понять. Чтобы помочь ему следует воспользоваться специальным пропом key={}. Он может быть значением любого типа, единственно требование — значение должно стабильно идентифицировать соответствующие данные.

    Если бы компонент выглядел так:

    class TodoList extends React.Component {
      state = {
        todos: [
          { id: 0, text: 'Commit' },
          { id: 1, text: 'Push' }
        ]
      }
      render() {
        return <ul>
          {this.state.todos.map(item => {
            return <li key={todo.id}>{ todo.text }</li>
          }
        </ul>
      }
    }


    То добавление элемента в начало массива, породило бы следующий стейт:

    const todos = [
      { id: 2, text: 'Init' },
      { id: 0, text: 'Commit' },
      { id: 1, text: 'Push' }
    ]


    И, снова, два древа элементов:

    // Начальный стейт
    <ul>
      <li>Commit</li> // id 0
      <li>Push</li> // id 1
    </ul>
    // Добавлен элемент
    <ul>
      <li>Init</li> // id 2 новый элемент отобразится в начале
      <li>Commit</li> // id 0
      <li>Push</li> // id 1 
    </ul>


    Благодаря подсказке, реакт не учтёт в дельте элементы чьи идентификаторы не изменились, и, как следствие, не будет делать лишних действий.

    Таким образом использовать индекс в массиве в качестве ключа — не лучшая идея, особенно если массив будет меняться. По той же причине не следует использовать Math.random() в качестве ключа, так вы почти гарантировано будете всегда получать нестабильные идентификаторы.

    Подробнее об этом можно почитать здесь — Reconciliation.
    Ответ написан
    5 комментариев
  • Как транспонировать матрицу не используя циклы?

    @pekc83
    const transpose = matrix => matrix[0].map((col, i) => matrix.map(row => row[i]));
    
    const baseMatrix = [[1, 2], [3, 4], [5, 6]];
    const transposedMatrix = transpose(baseMatrix);
    // [ [ 1, 3, 5 ], [ 2, 4, 6 ] ]
    Ответ написан
    3 комментария
  • В чем разница: функции первого класса и функции высшего порядка?

    k12th
    @k12th
    console.log(`You're pulling my leg, right?`);
    Функции высшего порядка -- функции, которые могут принимать другие функции и возвращать функции. first-class functions -- фича языка, позволяющая переменным содержать ссылки на функции. По сути -- разные вещи, но по отдельности смысла в них не много:)
    Ответ написан
    Комментировать
  • В чем разница: функции первого класса и функции высшего порядка?

    Ivanq
    @Ivanq
    Знаю php, js, html, css
    Погуглить слабо?

    Функция высшего порядка, в отличие от функции первого порядка, имеет один из трёх видов:

    1. Один из параметров функции также является функцией и она возвращает значение.
    2. Она возвращает функцию, но ни один из параметров не является функцией.
    3. И первый и второй пункт: функция возвращает функцию и один из параметров является функцией.

    Источник: https://github.com/anton-k/ru-neophyte-guide-to-sc...

    Таким образом, функция высшего порядка должна возвращать функцию и/или принимать одну функцию в параметр
    Ответ написан
    3 комментария
  • Что такое Less и Sass?

    Fesor
    @Fesor
    Full-stack developer (Symfony, Angular)
    Лень двигатель прогресса. Хороший пример - принцип DRY - Don't repeat yourself. Я весьма подозреваю что вы стараетесь соблюдать этот принцип когда делаете макеты или чем вы там занимаетесь. Так же я весьма уверен что вы хотя бы пытались чуть автоматизировать рутину своей повседневной работы. Так же у вас могли быть ситуации когда вы переиспользовали какие-то элементы. Мало ли.

    Так вот... CSS это тупая таблица стилей. Селектор и стили, ничего сверх умного тут придумать нельзя. Лет 5-10 назад было довольно модно держать один мегажирный CSS файл на 10К+ строк и радоваться жизни внося все больше изменений и т.д. Соответственно даже если вы соблюдаете всякие правила модульной верстки и все такое, у вас возникает несколько проблем:
    • организация стилей, то есть держать все в одном файле не удобно особенно когда проект длится годами
    • Дублирование стилей и селекторов. По мере развития проекта появляются какие-то снипиты которые можно реюзать. Так же у вас может появиться масса однообразных селекторов отличающихся лишь немного. При модульных подходах вложенности редко имеет место быть но все же имеет. Но не будем забывать что большинство фигачит селекторы просто так. В итоге если мы переместили блок или переименовали класс какого-то блока нужно отредактировать еще массу селекторов.
    • Привязка размеров и параметров к другим стилям, например у вас в стилях задана ширина блока, от нее зависят другие параметры, отступы для других блоков и т.д. Да, в css3 появился calc для этого но это было относительно недавно и только с недавних пор можно почти без опаски использовать эту штуку.
    • Таблицы стилей, как и HTML ориентированы на удобный разбор этого добра машиной, но не человеком. Человек же существо ленивое и как-то вот лень лишний раз скобку поставить или точку с запятой. Просто лень.


    Есть так же хорошее правило, или идея если хотите.... Если код можно сгенерить - его лучше сгенерить. То есть для решения всех выше перечисленных проблем придумали препроцессоры. Они как бы были и раньше всех этих scss/less/stylus но как-то не решали всех проблем и т.д. Что в итоге было предложено (перечисляю в том же порядке что и в списке выше).

    • У CSS есть такая штука как @ import. Но не очень круто импортировать сотню стилей в продакшене. Стоит сделать так что бы все стили были склеены при сборке проекта. Эта идея в итоге развилась и если разработчик использует это дело правильно, можно зайти в любой файл со стилями и увидеть список всего от чего зависят эти стили. Какие стили подключаются и т.д. Причем один файл с зависимостями может быть подключен в нескольких файлах а препроцессор сам разберется как и куда все вставлять сгенерив максимально оптимизированный по структуре файл. А разработчик получил четкую структуру файлов и возможность быстро найти где что и от чего зависит.
    • С селекторами проблему предложили решить наиболее логичным вариантом. Если у нас есть вложенные селекторы, то имеет смысл определять их внутри блока этого селектора. Это существенно упрощает поддержку стилей. Так же для управления снипитами и прочим добавили миксины - эдакие параметризованные или нет функции которые выплевывают шматок CSS. До появления штук вроде autoprefixer это был единственный способ писать поддерживаемые стили, использовать плюшки CSS3 и вообще новые плюшки и не сойти с ума от префиксов. Префиксы это только пример, там могут быть самые разные штуки позволяющие грамотно производить реюз стилей
    • Проблему зависимостей значений стилей друг от друга решили... собственно самым очевидным способом - переменные. Это удобно, легко поддерживать и в умелых руках это мощный инструмент. Нужно поменять базовые цвета - не нужно лазить по 100500 блоков и править значения руками, можно поправить переменные и все будет хорошо.
    • Насколько я помню SCSS/LESS не стремились решить эту проблему. Какие-то решения образовывались сами собой с течением времени. В плане минимализма и выразительности пожалуй сейчас самая крутая штука это stylus.


    Что в итоге произошло. В один прекрасный момент какие-то там рубисты придумали SCSS (они вообще не любят все что не в стиле ruby в плане минимализма и выразительности). Затем чуваки подумали и сказали, SCSS это круто но почему-то они используют синтаксис знакомый именно Ruby разработчикам а не обычные для CSS конструкции. В итоге реализовали LESS, причем его уже реализовали на javascript, что с наличием node.js позволило это все добро еще на одной платформе собирать. А так как под эту платформу и так плодили препроцессоры оно удачно вписалось.

    Далее уже шли какие-то модификации дальнейшие, вроде того же Stylus, где синтаксис упростили просто до нельзя.

    Личное мнение. На сегодняшний день я не вижу смысла использовать чистый CSS хоть на малых хоть на больших проектах. Вот вообще никакого.
    Ответ написан
    3 комментария
  • Знания Junior php разработчика?

    Fesor
    @Fesor
    Full-stack developer (Symfony, Angular)
    что должен знать идеальный джуниор (мое личное мнение):

    - Сетевой стэк. Нужно иметь хотя бы базовое представление о том как с сервером общаются. Ну то есть не нужно лезть в дебри, но понимать что такое HTTP или чем TCP от UDP отличается - нужно. В целом это пара часов чтения википедии.
    - GIT или любая другая распределенная VCS. Базовые навыки, что бы хотя бы понимал что есть git revert или git rebase, что такое фичабрэнчи и примерное представление как это работает и зачем надо.
    - Базовые основы unix. Ну то есть что бы не пугаться таких вещей как ssh хотя бы.
    - PHP. Без этого никуда. Он должен понимать что такое слабая динамическая типизация (не заучивать табличку кастов типов, а понимать плюсы и минусы, такая же история с приоритетами операторов - не заучивать а знать как избегать проблем с чтением кода)
    - Понимать что код чаще читают чем пишут, а потому не экономить 5 минут на написании кода, а писать так, чтобы сэкономить 30 минут человеку, разбирающемуся в куске кода.
    - Знать базовые вещи в плане безопасности. XSS и как защищаться, SQL инъекции и как защищаться, CSRF, MITM. Понимать что такое NDA, что данные пользователей - секретная информация. Как хэшировать пароли (не md5 а password_hash) и почему это важно.
    - Знать SQL. Глубоких знаний не требуется, нужно лишь понимание того, что такое нормальная форма, желательно разобраться с вопросом денормализации данных. Идеально иметь хотя бы базовые представления о том как работать с NoSQL решениями.
    - Процедурное программирование: почему глобальные переменные порождают сложность, что такое состояние, как можно использовать классы для изоляции состояния и т.д. Инкапсуляция. Инварианты, пост/пред условия, сохранение целостности...
    - Разделение ответственности. Это один из важнейших принципов, и упрощать все это до "mvc фреймворк" слегка неправильно. Вы должны понимать что от чего отделяете и главное зачем.
    - Автоматические тесты. Джуниор должен знать что это такое и иметь хотя бы минимальный опыт их написания. Должен понимать разницу между юнит и интеграционными тестами. Быть знакомым с пирамидой тестирования.
    - Уметь решать стандартные задачи не задавая слишком много вопросов. Например регистрацию пользователя по email-у вы должны написать, или авторизацию через соц сети, или комментарии, или новостную ленту.
    - Уметь дебажить. xdebug, blackfire и тд.

    В целом где-то за годик весь этот список можно влегкую покрыть с нуля.

    p.s. Я в списке специально не указывал ООП, поскольку всеравно первые пару лет у разработчиков выходит процедурщина на классах. Это не плохо, но того что в моем списке более чем должно хватать для решения стандартных задач. Но термины вроде "инкапсуляция/полиморфизм/наследование" требуются в обязательном порядке подавляющем количеством интервьюверов, а стало быть знать это надо. Единственное что - рекомендую в свободное время глубже погрузиться в этот вопрос а не тупо заучивать формулировки.

    Так же вещи вроде docker джуниорам знать не обязательно просто потому, что их врядли допустят сходу к управлению инфраструктурой. А так пару неделек на изучение и вперед.
    Ответ написан
    12 комментариев
  • Для чего нужно ООП?

    Stalker_RED
    @Stalker_RED
    Для управления сложностью.
    https://habrahabr.ru/post/169487/

    Все что сделано при помощи ООП можно написать и в процедурном стиле, например, но чем сложнее проект тем сложнее будет во всей этой каше разобраться. Весь смысл ООП - разбить большущую сложную систему на кучу отдельных ПРОСТЫХ объектов, методов, сущностей.
    А еще с ООП неразлучна абстракция. Чтобы можно было одну часть программы выбросить и подменить на другую.

    Сегодня у нас выводится на веб-страничку, по которой кликают мышкой, а завтра не мышкой - а тач пальцами. А послезавтра вообще в VR шлем, и управление голосом. И если система правильно спроектирована - ее не придется переделывать ПОЛНОСТЬЮ, а только ту часть, которая ответственна за ввод/вывод.
    Ответ написан
    Комментировать
  • Зачем нужны абстрактные классы (PHP)?

    Fesor
    @Fesor
    Full-stack developer (Symfony, Angular)
    типичный юзкейс для абстрактный классов - базовая реализация, уменьшение дублирования кода при появлении общего решения и т.д. Например у вас есть интерфейс с несколькими методами, и только 2-3 из них реализуются по разному. Выгодно вынести общую реализацию в базовый абстрактный класс.
    Ответ написан
    1 комментарий
  • Что такое Redux простыми словами?

    @KnightForce
    Чтобы понять как работает Redux тебе нужно норм вкуривать React.
    Хотя бы для того, чтобы не пугаться props.

    Есть у тебя React. Это все просто JS объекты.
    <Component /> - так позволяет писать движок jsx, который и React его использует.
    Так как структура компонентная, ты должен думать как обновить компоненты в в другой части страницы.

    Принцип такой: компонент обычно обновляется при получении новых свойств - props или когда меняется его объект состояния - state.

    Чтобы тебе обновить дальние друг от друга компоненты- тебе нужно продумать какие и где приходят свойства - чтобы пробросить функцию, которая вызовет перерисовку.

    Что делает Redux:
    Он не призывает отказываться от state.

    Но есть общий контейнер данных. И когда данные меняются - меняются и компоненты, которые отображают именно эти данные.

    Когда нужно что-то поменять - вызываешь dispatch - специальная функция reducer реагирует на это - и меняет данные как тебе нужно. Когда данные заменятся - компонент Propvider - вызывает рендер у своего дочернего компонента (тот что оборачивает Provider).
    Например:
    <Provider>
       <MyComponent />//Вот сюда Provider пробросит (запишет) новые props.
    </Provider>


    Записывает он это самое глобальное хранилище и все компоненты, для которых поменялись данные - перерисуются.

    mapStateToProps - указывает какую часть этого глобального хранилища будет предоставлять provider.
    Если у тебя оно такое:
    {
       chunkStore: {},
       some: {}
    }

    То если mapStateToProps вернет{store: store.chunkStore}то Provider в props своего потомка пробросит такое: store: store.chunkStore. И ты будешь обращаться внутри к store, но там будет только часть chunkStore (не весь объект, а его поле).

    mapDispatchToProps - т.к. subscribe нет, то это возвращает функции, которые могут внутри себя вызывать dispatch().

    action - описывает то что и на что ты хочешь поменять. Какое поле и какие данные туда поместить.
    Ответ написан
    Комментировать
  • Что такое Redux простыми словами?

    Лучшее объяснение Redux что я видел.
    getinstance.info/articles/react/learning-react-redux
    ba494148d28e422b4c7bd269de5bed09.png
    Ответ написан
    Комментировать
  • Событийный цикл в Node.js?

    @Coder321
    5a3d080aa9763119480381.png
    process.nextTick, setImmediate и setTimeout обрабатываются в первом тике eventloop
    Ответ написан
    Комментировать
  • Событийный цикл в Node.js?

    Findoss
    @Findoss
    JS dev
    вот отличное объяснение
    пропустите свой код через отличный инструмент loupe
    Ответ написан
    Комментировать
  • Чем отличаются интеграционное, unit и e2e тестирование на frontend?

    Fesor
    @Fesor
    Full-stack developer (Symfony, Angular)
    Как в юнит тестах тестить нажатие на кнопку? Или мы можем тестить только функцию-обработчик?


    В юнит тестах вы можете тестировать контроллер компонента, что мол он нужное состояние выставляет. DOM проверять не нужно. Механизм биндингов и так хорошо покрыт юнит тестами на уровне фреймворка. Чаще юнитами покрывают сервисы, ресолверы и прочее. Ими проверяют логику работы отдельных маленьких кусочков.

    в интеграционных можно уже потихоньку проверять DOM отдельных компонентов. Просто потому что вы могли опечататься при написании биндингов. Ну то есть цель интеграционных тестов - проверить что в сборке компоненты работают.

    В e2e (end to end) вы загружаете все приложение целиком и имитируете действия пользователей. Причем взаимодействие происходит насквозь. От кнопочки в браузере до запросов в базе данных на сервере (если есть бэкэнд). Это самый медленный вид тестирования и им стоит покрывать только позитивные сценарии.

    Читать про пирамиду тестирования.
    Ответ написан
    Комментировать
  • ООП + React + typescript как правильно создавать компоненты?

    rockon404
    @rockon404 Куратор тега React
    Frontend Developer
    Я так пишу:
    import * as React from 'react';
    import { connect, DispatchProp } from 'react-redux';
    import { connectedPropSelector } from './selectors';
    
    interface OwnProps {
      ownProp: string,
    }
    
    interface ConnectedProps {
      connectedProp: string,
    }
    
    type Props = OwnProps & ConnectedProps & DispatchProp<any>;
    
    interface State {
      someKey: string,
    }
    
    class Example extends React.Component<Props, State> {
      state = {
        someKey: 'someValue',
      };
      
      render() {
        const { ownProp, connectedProp } = this.props;
    
        return ( /* ... */ );
      }
    }
    
    const mapStateToProps = state => ({
      connectedProp: connectedPropSelector(state),
    });
    
    export default connect(mapStateToProps)(Example);


    Официальная документация
    Ответ написан
    1 комментарий
  • Как сделать простую прокрутку (без анимации) до якоря без изменения адресной строки (без jQuery на React)?

    rockon404
    @rockon404 Куратор тега React
    Frontend Developer
    Проще некуда:
    element.scrollIntoView();
    Демо

    В имплементации React как-то так:
    handleLinkClick = e => {
      e.preventDefault();
      const element = document.getElementById(e.target.href);
      element.scrollIntoView();
    };
    Ответ написан
    Комментировать
  • Как сделать исчезающую/появляющуюся стрелочку "вверх" на React?

    rockon404
    @rockon404 Куратор тега React
    Frontend Developer
    class ArrowUp extends Component {
      state = {
        isVisible: false,
      };
    
      componentDidMount() {
        window.addEventListener('scroll', this.handleScroll);
      }
    
      componentWillUnmount() {
        window.removeEventListener('scroll', this.handleScroll);
      }
    
      handleScroll = () => {
        if (window.scrollY >= SOME_VALUE  && !this.state.isVisible) {
          this.setState({ isVisible: true });
        } else if (window.scrollY < SOME_VALUE && this.state.isVisible) {
          this.setState({ isVisible: false });
        }
      };
    
      render() { /* ... */ }
    }
    Ответ написан
    Комментировать
  • Что значит и как перевести на русский tree shaking?

    rockon404
    @rockon404
    Frontend Developer

    Tree shaking (встряхивание дерева) — термин объединения модулей JavaScript, обозначающий статический анализ всего импортированного кода и исключение того, что на самом деле не используется.

    Для более прямолинейной аналогии рассмотрим живое дерево. Дерево встряхивается, и это заставляет мертвые листья отваливаться, оставляя только живые. В основе tree shaking лежит концепция живого включения кода (live code inclusion): мы включаем части, необходимые для начала, в отличие от удаления ненужных частей в конце — устранения «мертвого кода» (dead code elimination).

    Tree shaking зависит от import и export модулей ES2015. Выражения import и export составляют статическую структуру модуля приложения. Когда модули объединяются для развертывания приложения, tree shaker анализирует статическую структуру модуля, чтобы исключить неиспользуемый экспорт, уменьшив размер окончательного пакета.

    ES2015 позволяет указывать явный импорт. Например, вместо импорта всей библиотеки RxJS мы можем импортировать именно то, что хотим:

    import { BehaviorSubject } from 'rxjs/BehaviorSubject';

    Это отличается от динамического выражения require, используемого CommonJS или AMD. Tree shaking использует этот принцип для перемещения по зависимостям и исключения ненужных зависимостей для уменьшения размера приложения.

    Принцип tree shaking не нов, но он только недавно был популяризирован с помощью сборщика rollup.js, объединяющего модули приложения. Webpack 2 также использует tree shaking. Концепция tree shaking также распространена в Angular с компиляцией AOT.

    Источник
    Ответ написан
    Комментировать
  • Для создания приложения на React, нужно ли сначала целиком делать верстку приложения?

    rockon404
    @rockon404 Куратор тега React
    Frontend Developer
    Нет, это будет двойная работа. В реальном проекте программист:
    1. Описывает компонент
    2. Пишет JSX разметку в render
    3. Стилизует компонент, в зависимости от выбранной технологии
    4. Пишет необходимые методы и слушатели
    Ответ написан
    1 комментарий