• Хотите задать вопрос администрации Тостера?

    sfi0zy
    @sfi0zy
    Creative frontend developer
    Было бы хорошо иметь возможность закреплять у себя в профиле не самые залайканные ответы, а те, которые сам выбрал. Чтобы там были серьезные ответы на сложные вопросы (которые не так много людей могут заценить), а не философские размышления и удачно подобранные ссылки.
    Ответ написан
    6 комментариев
  • Кто то уже юзал в проектах новое Context Api в 16.3?

    miraage
    @miraage
    Старый прогер
    Context ни в какой Вселенной не является заменой Redux.
    Ответ написан
    2 комментария
  • Какие ресурсы понадобятся для разработки своей медицинской CRM?

    nki
    @nki
    bezkart.ru готовая система лояльности
    Есть ли смысл вообще разрабатывать самим, ведь есть готовые решения?

    Посмотрите готовые решения, если они решают ваши задачи, то имеет смысл их использовать. Так вы раньше начнете работать с системой, а не ждать когда будет сделана новая.
    Если же существующие решения не отвечают вашим требованиям (даже с доработкой), то естественно придется ввязаться в разработку.
    Ответ написан
    Комментировать
  • Как соединить front и back?

    @dfv123
    На клиенте делаете запрос к API сервера, где определено по какому маршруту и какие данные отдать/принять. Обмен в формате json.
    Ответ написан
    Комментировать
  • Как начальник может контролировать фрилансера по часам удалённо?

    @vism
    Будьте готовы к тому, что ваши 9 часов проведенных на работе = 4-5 по тайм трекеру.
    И если порой на работе можно весь день делать видимость работы, по тайм трекеру так не выйдет
    Ответ написан
    Комментировать
  • Зачем при верстке добавлять классы "js"? Я понимаю - разделение представление и логики. Но зачем это нужно? Зачем нужно это разделение?

    Плохого в том, что у вас есть 5 разных кнопок, но все запускают одно и то же событие. Вы будете вешать один и тот же обработчик на 5 разных айдишников? или все-таки создадите один класс, пропишите только для него обработчик и будете писать этот класс для всех кнопок, на которые вы хотите повесить какое-то действие? Я думаю ответ очевиден. А классы вида .js-add-to-cart делаются для того, чтобы было проще отыскать ваш функционал в коде, ведь сразу понятно что сюда повешен обработчик какой-то, чем пытаться потенциальный ID выискивать в вашем js коде.
    Ответ написан
    9 комментариев
  • Как работать с API?

    rockon404
    @rockon404 Куратор тега React
    Frontend Developer
    1. да
    2. да
    3. лучше сохранять в state данные, а мапить их уже в render
    Ответ написан
    1 комментарий
  • Какой выбрать софт для кросспостинга?

    wowgamr
    @wowgamr
    По первой части могу порекомендовать сервис, которым когда-то пользовался - Hooppy.
    Телеграма там нет, но разработчик довольно общительный, по вашей просьбе, думаю, добавит.
    Ответ написан
    1 комментарий
  • Почему в setState имя свойства обёрнуто в квадратные скобки?

    0xD34F
    @0xD34F Куратор тега React
    Вычисляемые имена свойств.

    Этот метод стоит на событие onChange.

    Сомнительное утверждение. "На событие" "стоит" не handleChange, а функция, которую он возвращает. По-видимому, необходимо единообразно обрабатывать события, возникающие в разных местах - единственные отличия, это имена обновляемых свойств, для каждого из которых создаётся собственный обработчик. Что, кстати, делать вовсе не обязательно - есть вариант прицепить значение type к элементу в виде data-атрибута, и тогда можно будет использовать общий обработчик:

    handleChange = ({ target: { value, dataset: { type } } }) => {
      if (value.length <= limits.user.max) {
        this.setState({
          [type]: value,
        });
      }
    }

    <input onChange={this.handleChange} data-type="xxx">
    <input onChange={this.handleChange} data-type="yyy">
    <input onChange={this.handleChange} data-type="zzz">
    Ответ написан
    Комментировать
  • Вложенные роуты в React Router 4. По ссылке 'user1/commit1' срабатывает компонент для 'user1/'. Как это можно сделать корретно?

    0xD34F
    @0xD34F Куратор тега React
    Как это можно исправить?

    Добавить exact - вижу, это вы и сами сообразили. Ещё можно изменить порядок роутов (рендерится первый подходящий):

    <Switch>
      <Route exact path="/" component={HomePage} />
      <Route path="/:user/:commit" component={CommitPage} />
      <Route path="/:user" component={UserPage} />
    </Switch>

    Что стоит изучить, чтоб разобраться в вопросе?

    Документацию.
    Ответ написан
    Комментировать
  • Хранение (для вёрстки) данных состояния приложения в Redux. Адекватно ли?

    rockon404
    @rockon404 Куратор тега React
    Frontend Developer
    Если, что-то проще сделать без redux, не надо это туда тянуть. Это касается всего: форм, модалок, фильтров и прочего.
    Определять версию лучше по user agent, а передавать эти данные через контекст.
    Ответ написан
    Комментировать
  • Глобальная видимость кастомной функции в любом месте кода?

    lavezzi1
    @lavezzi1
    Создайте файл utils.js и кладите подобные функции туда.

    Экспортируете так в utils.js
    export function indexToFind () {...}

    Затем в файле где хотите использовать
    import { indexToFind } from 'utils.js';

    Это самый адекватный подход. У вас таких функций может быть с сотня, по мере роста проекта, засирать window или vue global плохая идея для таких мелких функций.

    А вот хороший пример что можно записывать в vue global:

    main.js
    import axios from 'axios';
    
    Vue.prototype.$http = axios;
    Ответ написан
    Комментировать
  • Почему Promise pending?

    rockon404
    @rockon404 Куратор тега React
    Frontend Developer
    Вы неправильно работаете с асинхронным кодом. Вызывать его в render неправильно.
    Вы что сделать то хотите?
    Для работы с асинхронными вызовами основанными на Promise используйте метод then или async/await функции.
    Пример использования метода then:
    isValidEmail("mail@gmail.com").then(result => someAction(result));

    Пример использования async/await:
    async someHandler() {
      const result = await isValidEmail("mail@gmail.com");
    
      return someAction(result);
    }
    
    async someOtherHandler() {
      const result = await isValidEmail("mail@gmail.com");
      
      /* вызов someOtherAsyncAction тоже возвращает Promise, поэтому ждем 
         и возвращаем только когда придет результат, для этого используем 
         ключевое слово await                                             */
      return await someOtherAsyncAction(result); 
    }
    Ответ написан
    3 комментария
  • Где выгоднее жить программисту, в Москве или Новосибирске?

    DmitriyEntelis
    @DmitriyEntelis
    Думаю за деньги
    Поддержу Максим
    Если устраиваться fulltime в офис - то только Москва.
    Да, аренда дороже, квартира с приличным ремонтом в паре минут от метро будет стоить ~30-35, но карьерный рост достаточно быстр и даже если Вы просядете в деньгах в первые полгода, потом это все окупится.

    Опять же тут море всяких активностей, выбор которых в небольшом городе гораздо скромнее.

    Я например люблю вкусно пожрать.
    В моем родном городе мест где вкусно кормят штук 5 - ходить в них по кругу надоедает крайне быстро.
    В МСК они открываются и закрываются быстрее чем я успеваю в них ходить :)

    Театры, кино, выставки, профильные конференции итд - всего море.
    Ответ написан
    Комментировать
  • Почему пропсы из Редакса в обработчике Реакт не видит, когда в render(){} видит?

    rockon404
    @rockon404 Куратор тега React
    Frontend Developer
    Вы передаете метод clickHandle в колбек слушателя события click, при вызове метод теряет контекст, так как вызывается не на вашем объекте. this в таком случае ссылается не на ваш объект, а на undefined. Так как babel при трансляции добавляет 'use strict' (иначе, при выполнении в браузере, ссылался бы на window). Исправить это можно несколькими способами:
    1. переделать обработчик из метода класса в class field arrow function:
    было:
    clickHandle(e) {
      // some code
    }

    стало:
    clickHandle = e => {
      // some code
    };

    class field arrow function получает контекстом экземпляр класса при инициализации и всегда ссылается на него, куда бы вы ее не передали. Это экспериментальная возможность JavaScript и в спецификации ее пока нет. За трансляцию этой конструкции в валидный код отвечает babel.
    Результат, который будет получен после трансляции, можно посмотреть тут. Строки с 23 по 28.

    2.забиндить его в конструкторе на экземпляр класса:
    constructor(props) {
      super(props);
      this.clickHandle = this.clickHandle.bind(this);
    }

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

    3. обернуть в стрелочную функцию в render:
    <SomeComponent onClick={() => this.сlickHandle()} /> // контекст не будет потерян

    При оборачивании в стрелочную функцию происходит следующее: сама функция использует как контекст ваш объект, поэтому при вызове метод будет вызван на вашем объекте и this в самом методе будет ссылаться на объект. Этот вариант разумно использовать, только тогда, когда в хандлер необходимо передать свои аргументы, помимо event:
    <ListItem
      key={item.id}
      onClick={e => this.сlickHandle(item.id, e)}
    >
      {item.name}
    </ListItem>

    так как движок вынужден определять контекст для стрелочной функции каждый рендер, а на это уходит дополнительное процессорное время.

    Как метод теряет контекст.
    Разберем на примере объекта. То же самое происходит в случае с классом, но мы будем использовать в примере объект:
    var john = {
      firstName: 'John',
      getName() {
        return this.firstName;  // this - контекст вызова и это не всегда наш объект
      }
    }


    Сценарий 1:
    console.log(john.getName()); // john
    Тут мы вызываем метод на объекте. Контекстом будет наш объект.

    Сценарий 2:
    var foo = {
      firstName: 'foo',
    };
    var foo.getName = john.getName;
    console.log(foo.getName()); // foo

    Тут мы передаем метод объекта john в свойство объекта foo без вызова и следующей строкой вызываем его на нем. Контекстом в этот раз будет объект foo. Ошибки не будет только потому, что у объекта foo есть свойство fullName

    Сценарий 3:
    var bar = john.getName;
    console.log(bar()); // undefined

    В данном случае в стандартном режиме контекстом будет window, а в строгом режиме вылетит исключение:
    Cannot read property 'firstName' of undefined
    так как this в строгом режиме будет ссылаться на undefined

    Когда вы передаете метод в колбек onClick или в любой другой колбек события, вызов идет подобно третьему сценарию. Поэтому вы должны позаботиться о том, чтобы ваш метод не терял контекст, используя один из способов приведенных выше.
    Ответ написан
    2 комментария
  • Как сделать экспорт в react\redux после запроса API?

    rockon404
    @rockon404 Куратор тега React
    Frontend Developer
    Сам вопрос поставлен вразрез с концепцией Redux, да и самой модульной концепцией JavaScript. Вам не надо пытаться экспортировать модуль после запроса, так делать нельзя. Вам надо задать начальное состояние и определить там ключи состояния isLoading, isError. При инициализации приложения произойдет запрос на сервер за данными и пока они не пришли isLoading будет иметь значение true, вы, в идеале, в этот момент должны показывать пользователю прелоадер.
    Ну, а то что вы пытались сделать это в корне не правильно.

    При использовании redux-thunk должно получится, что-то вроде:
    import { fetchInitialDataApi } from './api';
    
    const FETCH_INITIAL_DATA_REQUEST = 'FETCH_INITIAL_DATA_REQUEST';
    const FETCH_INITIAL_DATA_SUCCESS = 'FETCH_INITIAL_DATA_SUCCESS';
    const FETCH_INITIAL_DATA_ERROR = 'FETCH_INITIAL_DATA_ERROR';
    
    const fetchInitialDataRequest = () => ({ type:  FETCH_INITIAL_DATA_REQUEST });
    const fetchInitialDataSuccess = data => ({
      type:  FETCH_INITIAL_DATA_SUCCES,
      payload: data,
    });
    const fetchInitialDataError = error => ({
      type:  FETCH_INITIAL_DATA_ERROR,
      payload: error,
    });
    
    const fetchInitialData => async dispatch => {
      try {
        dispatch(fetchInitialDataRequest());
        const { data } = await fetchInitialDataApi();
        dispatch(fetchInitialDataSuccess(data));
      } catch error {
        dispatch(fetchInitialDataError(error));
      }
    };
    
    const initialState = {
      data: {},
      isLoading: false,
      isError: false,
      error: null,
    };
    
    export default function(state = initialState, action) {
      const { type, payload } = action;
    
      switch (type) {
        case FETCH_INITIAL_DATA_REQUEST:
          return {
            ...state,
            isLoading: true,
            isError: false,
            error: null,
          };
        case FETCH_INITIAL_DATA_SUCCESS:
          return {
            ...state,
            data: payload,
            isLoading: false,
          };
        case FETCH_INITIAL_DATA_ERROR:
          return {
            ...state,
            isLoading: false,
            isError: true,
            error: payload,
          };
      default:
        return state;
      }
    }


    Если же хотите получать начальные данные сразу и они статичные, то пишите их в шаблон страницы приложения в window._data и забирайте через reducer:
    export default (state = window._data) => state;
    Ответ написан
    2 комментария