• Как сформировать массив?

    rockon404
    @rockon404
    Frontend Developer
    ES6:
    const map = {};
    
    srcArray.forEach(({ ID, ...Coords }) => {
      map[ID] = map[ID] || { ID, Coords: [] };
      map[ID].Coords.push(Coords);
    });
    
    const resultArray = Object.values(map);

    или без rest оператора:
    const map = {};
    
    srcArray.forEach(({ ID, lat, lng }) => {
      map[ID] = map[ID] || { ID, Coords: [] };
      map[ID].Coords.push({ lat, lng });
    });
    
    const resultArray = Object.values(map);

    еще ES6:
    const resultArray = 
      Object.values(srcArray.reduce((map, { ID, ...Coords }) => {
        map[ID] = map[ID] || { ID, Coords: [] };
        map[ID].Coords.push(Coords);
    
        return map;
      }, {}));

    без использования rest:
    const resultArray = 
      Object.values(srcArray.reduce((map, { ID, lat, lng }) => {
        map[ID] = map[ID] || { ID, Coords: [] };
        map[ID].Coords.push({ lat, lng });
    
        return map;
      }, {}));


    ES5:
    var map = {};
    var resultArray = [];
    
    srcArray.forEach(function(el) {
      map[e.ID] = map[el.ID] || { ID: el.ID, Coords: [] };
      map[el.ID].Coords.push({ lat: el.lat, lng: el.lng });
    });
    
    for(var key in map) {
      resultArray.push(map[key]);
    }
    Ответ написан
    Комментировать
  • Как делать нормальный запрос в fetch?

    rockon404
    @rockon404
    Frontend Developer
    Можно использовать axios
    axios.post('/login', { body: 'Hello' })
      .then(function(res) {
        alert(res.data);
      });


    Запросы к северу хорошо оформлять отдельными функциями:
    const login = options => axios.post('/login', options);

    ES5 версия:
    const login = function(options) {
      return axios.post('/login', options);
    }


    Ее использование в коде:
    login(options).then(res => alert(res.data));

    ES5 версия:
    login(options).then(function(res) {
      alert(res.data);
    });

    в асинхронной функции:
    async () => {
      try {
        const { data } = await login(options);
        /* some other logic */ 
      } catch e {
        console.log('Server request error:', e);
      }
    }
    Ответ написан
    Комментировать
  • Как вызвать alert() при пропадании выделения (slection) с текста?

    rockon404
    @rockon404
    Frontend Developer
    Можно так:
    var prevSelection;
    
    document.addEventListener('mouseup', function() {
      var selection;
      
      if (window.getSelection) {
        selection = window.getSelection().toString();
      } else if (document.selection) {
        selection = document.selection.createRange().text;
      }
      
      if (!selection && prevSelection.length) {
        alert('Text uselected');
      }
      
      prevSelection = selection;
    });

    Демо.
    Ответ написан
    2 комментария
  • Выходит ошибка при сборке проекта с помощью Webpack?

    rockon404
    @rockon404
    Frontend Developer
    Поправьте в .babelrc:
    {
      "presets": ["env", "react", "stage-0"],
      "plugins": ["transform-decorators-legacy"]
    }

    и уберите из конфига. Незачем дублировать.

    Либо поправьте в конфиге:
    options: {
      presets: ['env', 'react', 'stage-0'],
      plugins: ['transform-decorators-legacy']
    }
    Ответ написан
    7 комментариев
  • Почему перезаписывается массив?

    rockon404
    @rockon404
    Frontend Developer
    А вы что сделать хотели?
    Ваш цикл никогда не закончится, так как вы постоянно добавляете элементы в массив. Перед каждой итерацией идет проверка:
    i < this.arr.length
    А у вас и i и this.arr.length после каждой итерации на 1 увеличиваются и как следствие this.arr.length всегда больше.

    Возможно вы хотели сделать, что-то вроде этого:
    this.httpService.getList().subscribe(data => {
      this.arr = [...this.arr, ...data];
    });

    или:
    this.httpService.getList().subscribe(data => {
      this.arr = this.arr.concat(data);
    });


    Если важно расширять старый массив, а не возвращать новый то:
    this.httpService.getList().subscribe(data => {
      data.forEach(el => this.arr.push(el));
    });
    Ответ написан
  • React ,Redux && auth?

    rockon404
    @rockon404 Куратор тега React
    Frontend Developer
    const PrivateRoute = ({ component: Component, isAuth, ...rest }) => (
      <Route {...rest} render={props => (isAuth
          ? <Component {...props} />
          : <Redirect to='/login' />
        )}
      />
    );
    
    const mapStateToProps = state => ({
      isAuth: state.isAuth,
    });
    
    const mapDispatchToProps = {
      authenticated,
    };
    
    export default connect(mapStateToProps, mapDispatchToProps)(PrivateRoute);
    Ответ написан
  • Какой стек выбрать для не сложного многопользовательского SPA?

    rockon404
    @rockon404
    Frontend Developer
    Для вашей задачи можно использовать React/Vue + Webpack + Koa + ReactNative/Weex + MongoDB/MySQL/GraphQL + Docker + Nginx + Git.
    1. На React вы сможете написать как само веб приложение, так и нативные мобильные клиенты под Android и IOS с помощью React Native. Можно выбрать Vue - он проще для новичка и на нем также можно писать нативные мобильные приложения c Weex. Использовать Angular не советую, так как порог вхождения у него выше, а грамотную архитектуру написать сложнее. Тут нужен опыт или советы опытного разработчика.
    2. Webpack. Как не крути, а со сборкой фронтенда вам придется разобраться. В современной разработке без этого никуда. Использовать решения вроде create-react-app, лично я не советую. Как альтернативу для быстрого старта, лучше выбрать ReKit. Это тулкит для разработки на React, содержащий в себе полноценную IDE, начальную структуру проекта с роутингом и Redux, DevServer, HMR, инструменты для тестирования и много других интересных фич, вроде аналитики. Еще в сгенерированном проекте полностью отсутствует вендорная магия, вроде react-scripts в create-react-app и у вас не будет каких либо проблем с миграцией.
    3. Если выберите Koa для сервера, вам, как минимум, не придется изучать еще один ЯП. API накидать на нем плевое дело для опытного разработчика, вам же придется изучать статьи и репозитории с примерами на github. Можно выбрать Express это предшественник Koa, и в силу возраста, статей и ответов на типовые вопросы на stackoverflow для него больше.
    4. Выбор БД не принципиален.
    5. Использование Docker так же не обязательно, но разобравшись сразу, вы во многом облегчите себе жизнь и не столкнетесь с ситуацией, что ваш проект который вроде работал локально, не хочет заводиться на удаленном сервере.
    Ну Nginx и Git думаю в представлении и обосновании мотивации к использованию не нуждаются.
    Так же, возможно, хорошим решением будет использование облачных сервисов вроде Amazon Web Services

    Прежде чем браться изучать эти инструменты вам обязательно надо хорошо изучить JavaScript, HTML и CSS.

    По приложению вам понадобится:
    1. Веб сайт с описанием сервиса и формой входа/регистрации
    2. Клиентское приложение
    3. Админка
    4. Мобильные приложения

    Потратьте время на пользовательские истории, UML диаграммы и схемы интерфейсов. Используйте трекер задач.

    Мое мнение, чтобы изучить все вышеперечисленное, а начинать вам, судя по всему, придется начать с основ JavaScript, HTML и CSS, уйдет уйма времени. Чтобы после изучения всего вышеперечисленного, научиться на всем этом писать хороший код, уйдет еще больше времени. Одно дело изучить инструменты, совсем другое научиться писать хороший код, решать типовые задачи, организовывать архитектуру. А решать задачи всех планов, вам придется как по фронтенду, так и по бекенду.

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

    Если на рынке уже есть сильный конкурент и ваш сервис просто будет повторять его бизнес модель, то он вряд ли взлетит, только потратите силы и время. Обязательно изучите рынок прежде чем, что-либо предпринимать.
    Ответ написан
    2 комментария
  • В массиве меняется весь массив с объектами?

    rockon404
    @rockon404 Куратор тега React
    Frontend Developer
    Вы передаете ссылку на один и тот же массив всем элементам массива graffik:
    grafik.forEach(elem => {
      elem.attr = attr; 
    });


    Когда передаете напрямую, срабатывает именно потому, что каждый раз создаете новый массив с новыми объектами.

    Вам надо передавать копии массива с копиями вложенных объектов. Сделать это можно так:
    grafik.forEach(elem => {
      elem.attr = attr.map(el => ({ ...el }));
    });

    Либо, если не используете spread оператор:
    grafik.forEach(elem => {
      elem.attr = attr.map(el => Object.assign({}, el));
    });
    Ответ написан
    2 комментария
  • Почему объект не ссылается сам на себя?

    rockon404
    @rockon404
    Frontend Developer
    Изначально переменной list присваивается значение null. Дале, каждую итерацию выполняется код:
    list = { value: array[i], rest: list };
    Сначала выполняется правая часть выражения, создается объект со свойством value принимающим значение элемента массива по индексу i, и свойством rest принимающим значение list, первую итерацию оно null:
    { value: 10: rest: null };
    Ну, а затем созданный объект присваивается переменной list. И так каждую итерацию.

    Простой пример как это работает:
    var x = 10;
    
    x = x + 5;

    Сначала вычисляется правая часть, затем происходит присваивание:
    x = 10 + 5;
    или:
    x = 15;

    А так можно сделать ссылку на себя:
    var obj = {       // создаем объект доступный по ссылке obj
      prop: 'example prop' 
    };
    
    obj.self = obj;  // добавляем в объект свойство self ссылающееся на сам объект
    Ответ написан
    1 комментарий
  • Почему побитовые операторы не работают?

    rockon404
    @rockon404
    Frontend Developer
    У вас две опечатки. Объявленны summidle и sum, а используются sumidle и summ.
    Учитесь анализировать ход выполнения кода и отлаживать его в консоли браузера.
    Лучше использовать логическое && и строгое сравнение:
    var summidle = 3;
    var sum = 16;
    
    if (summidle === 3 && sum > 11 && sum < 22){
      alert("legend");	
    }
    Ответ написан
    Комментировать
  • Почему не получается подключить обработку клавиатурного ввода?

    rockon404
    @rockon404
    Frontend Developer
    В вашем коде нигде не вешается слушатель на событие ввода.
    Еще очень плохой тон, тащить в JS и CSS стиль форматирования С++/C#.
    Ответ написан
    5 комментариев
  • Как передать значения от ребенка родителю в React?

    rockon404
    @rockon404 Куратор тега React
    Frontend Developer
    1. Нельзя использовать this.state в setState, так как setState асинхронный метод и на момент вызова состояние может успеть измениться. Для обновления состояния по текущему надо передавать в setState функцию возвращающую новый объект состояния. В момент вызова первым аргументом туда придет актуальное состояние компонента:
    this.setState(prevState => ({
      tasks: [
        ...prevState.tasks,
        { content, comments: [], active: true},
      ],
    }));

    2. Хандлеры лучше биндить в конструкторе, либо использовать inline class arrow function вместо метода класса:
    bind в конструкторе:
    constructor(props) {
      super(props);
      this.onAddItem = this.onAddItem.bind(this);
    }

    inline class arrow function:
    onAddItem = content => {
      // some stuff
    };


    3. С формами гораздо удобней работать через контролируемые элементы:
    class Example extends Component {
      state = {
        inputValue: '',
      };
    
      handleChange = e => { 
        const { name, value } = e.target;
        
        this.setState({
          [name]: value,
        });
      };
    
      render() {
        const { inputValue } = this.state;
    
        return (
          <Wrapper>
            <input
              name="inputValue"
              value={inputValue}
              onChange={this.handleChange}
            />
            ...
          </Wrapper>
        );
      }
    Ответ написан
    Комментировать
  • Что делает оператор new?

    rockon404
    @rockon404
    Frontend Developer
    Добавлю к вышенаписанному, что работу оператора new можно симитировать следующей функцией:
    function newExpression(constructor) {
      if ( typeof constructor !== 'function') {
        throw new TypeError(constructor + 'is not a constructor');
      }
    
      var args = Array.prototype.slice.call(arguments, 1);
      var obj = Object.create(constructor.prototype);
      
      return constructor.apply(obj, args) || obj;
    }

    Демо.
    В отличии такой имитации настоящий оператор new успешно создаст экземпляр даже по забинженому на другой контекст конструктору (по факту, возвращенной привязанной функции), так как оператор new игнорирует преданное значение this. Аргументы же будут применены из [[BoundArguments]]:
    var User = function(name) {
      this.name = name;
    }
    
    User.prototype.getName = function() {
      return this.name;
    }
    
    const obj = {};
    
    User = User.bind(obj, "Sarah");
    
    var john = new User('John');
    
    console.log(john.getName()); // 'Sarah'


    Спецификации new и [[Construct]]
    Ответ написан
    Комментировать
  • Как будет с ES6?

    rockon404
    @rockon404 Куратор тега React
    Frontend Developer
    Можно так:
    В компоненте в из которого передаете хандлер определяете его как inline arrow class function:
    class Parent {
      onNoteDelete = note => {
        // some stuff
      };
    }

    Такие функции не теряют контекст. Либо, можно забиндить хандлер в конструкторе, как посоветовали выше.

    Метод render:
    render() {
      const { notes, onNoteDelete } = this.props; 
      
      return(
        <div className="notes-grid" ref="grid">
          {notes.map(note => (
            <Note 
              key={note.id} 
              color={note.color}
              onDelete={() => onNoteDelete(note)}
            >
              {note.text} 
            </Note>
           ))}
        </div>
      )
    }


    Для значений которые не переопределяются лучше использовать const, а не let. Так другие программисты будут сразу видеть, что значение не переопределяется и как следствие ваш код будет читаемей.
    Ответ написан
    Комментировать
  • Почему не компилируется less или sass в webpack?

    rockon404
    @rockon404
    Frontend Developer
    Вы все неправильно поняли.
    includePaths
    An array of paths that LibSass can look in to attempt to resolve your \@import declarations. When using data, it is recommended that you use this

    "./public/css/style.css" - не существует, вот он и ругается.

    Для того чтобы генерировались файлы стилей, надо использовать ExtractTextPlugin.
    Ответ написан
    1 комментарий
  • При одалживании метода объект живет или выпиливается?

    rockon404
    @rockon404
    Frontend Developer
    Во-первых вы не отдалживаете метод, а получаете на него ссылку. Во-вторых ссылка на метод, в вашем случае, находится не в самом объекте, а является свойством прототипа. В-третьих в JavaScript объекты удаляются по принципу достижимости. Если на объект нет ни одной ссылки, то занимаемая им память будет очищена при первой же возможности. Если же на объект есть ссылки, то это еще не гарантия, что память не будет очищена.
    Например:
    let foo = {};
    let bar = {};
    foo.barLink = bar;
    bar.fooLink = foo;
    
    foo = bar = null;


    На объекты есть ссылки barLink и fooLink, но они недостижимы, ведь мы не можем обратиться к этим свойствам, после того как переназначили переменные foo и bar,. Поэтому память занимаемая объектами будет очищена, несмотря на наличие ссылок.

    Ваш массив будет уничтожен сборщиком мусора сразу же после выполнения строки в которой используется.

    Другое дело, если мы сначала забиндим метод на наш объект:
    class Person {
      constructor(name) {
        this.name = name;
      }
      printName() {
        console.log(this.name);
      }
    }
    
    let john = new Person('John');
    const obj = {};
    
    obj.printJohnName = john.printName.bind(john);
    john = null;
    
    obj.printJohnName();  // 'John'

    Объект ранее доступный по ссылке john не будет удален, так как мы забиндили на него функцию и в ней есть скрытое свойство [[BoundThis]], ссылающееся на него:
    5a84af46ab784660788834.png
    Ответ написан
    Комментировать
  • Как создать такой массив с данными?

    rockon404
    @rockon404
    Frontend Developer
    const map = {};
    
    srcArray.forEach(({ title, value }) => {
      map[title] = map[title] || { title, data: [] };
      map[title].data.push({ money: value });
    });
    
    const resultArray = Object.values(map);
    Ответ написан
    2 комментария
  • Как загрузить и хранить фото на сервере (React+Express+Mongo)?

    rockon404
    @rockon404 Куратор тега React
    Frontend Developer
    Используйте FormData для отправки файлов:
    const formData = new FormData();
    
    formData.append('file', someFile);
    axios.post('/uploadFile', formData, {
      headers: {
        'Content-Type': 'multipart/form-data',
      },
    });


    На сервере используйте midlleware для обработки multipart/form-data. Вам подойдет: formidable, busboy, multer или любое другое middleware, решающее эту задачу.
    Ответ написан
    3 комментария
  • Почему не вешается обработчик на react компонент?

    rockon404
    @rockon404 Куратор тега React
    Frontend Developer
    А с чего вы взяли что он там должен быть? Вам, думаю, стоит подтянуть основы JavaScript.

    Если используете синтаксис ES6, используйте импорты и экспорты:
    import React from 'react';

    export default Task;

    Хандлеры лучше биндить не в render, а в конструкторе:
    constructor(props) {
      super(props);
    
      this.state = {
        isOpened: false,
      };
    
      this.clickHandler = this.clickHandler.bind(this);
    }


    Или определяйте хандлер как class field arrow function:
    clickHandler = e => {
      // your stuff
    };

    Такая функция привязана к контексту экземпляра и биндить ее не надо.
    create-react-app поддерживает такой синтаксис из коробки.

    Нельзя передавать текущее состояние в метод setState, так как это асинхронный метод, к моменту вызова состояние может успеть измениться и будет использовано старое значение. Чтобы обновить состояние на основе предыдущего передавайте в setState функцию возвращающую объект. При вызове, первым аргументом в нее придет актуальное состояние на момент обновления:
    this.setState(prevState => ({
      isOpened: !prevState.isOpened,
    }));


    Вместо var используйте const для неизменяемых значений и let для изменяемых.

    Наконец, следите за чистотой кода. Вот хорошие гайдлайны от Airbnb:
    Гайдлайн Airbnb по JavaScript
    Гайдлайн Airbnb по React
    Ответ написан
    6 комментариев