Pull to refresh
0
0
Кирилл Шумилов @brusher

Javascript разработчик

Send message

Справедливости ради хочу отметить, что даже по кнопкам 200х200 можно легко промахнуться, а расстояние в этом деле и скорость прицеливания играют немаловажные роли, и пренебрегать ими не стоит даже в грубых спорах об отступах, как исключительно эстетической составляющей интерфейса. :-Р

Если так посудить, то это не функциональный дизайн, а опять инженерное решение. Раньше перед инженером задача была ускорить заточку большим инструментов (сделали круглый камень и раб крутит ручку), а теперь стоит задача удешевить работу (избавиться от лишнего рта). И тут появляется ножной привод, теперь нужен только один рабочий.

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

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

Чтобы не включать всюду реакт вебпаку в конфигурации можно указать externals.
В целом же, по-моему, затея сомнительная и не понятно как решить какие данные ему скормить (в примере только текущая дата).
Интересно узнать какая за этим бизнес-задача стояла :)

Если я не ошибаюсь — вы потеряли someData к моменту манипуляции с данными.
А вот вариант с Promise.all — в данном случае лучший, если только второй запрос не требует информации из первого :)
Если копнуть поглубже в концепции и особенности реакта с редуксом, то вы заметите, что там есть некоторые особенности. И, как мне кажется, чтобы в головах разработчиков не возникало лишней путаницы и были данны различные наименования.

Например:
Действия (аналог событий) — главное отличие от привычных нам событий, что на них нельзя подписываться для изменений данных в стейте (модели), их можно только вызывать. Но есть всякие штуки типа redux-saga, которые позволяют создавать подписки для получения неких сайд-эффектов, но это другая песня и делать это нужно осторожно.
Редюсеры (аналог моделей) — все модельки упаковываются в один стор. Главная особенность, что никто напрямую не дергает модельку, а каждая моделька сама применяет к себе действия (события) и, возможно, в следствии меняется. И стор всегда возвращает консистетное состояние всей системы (всех моделей).
Контейнеры (statefull components) (аналог контроллеров) не должен выполнять какой-то логики обработки данных, он должен ее лишь получать и назначать вьюхе (все как в правильном активном MVC). И привязывать вызов экшенов (! но не решать какую модельку когда потрогать и как). И каждый такой контейнер может работать сразу с множеством «моделей» (получать любые данные из стора), хотя привычные всем контроллеры чаще всего работают с одной моделькой. А в связке с редуксом и вовсе многие рекомендуют делать их тоже стейтлесс и все стейты хранить в общем стейте — это снимает множество боли.
Компоненты — да, привычные всем тупые вьюхи.


Отсюда следует вывод, что называть это MVC не верно, т.к. оно имеет ряд концептуальных отличий и одно из самых жирных — отсутствие pub/sub. (с тем же успехом можно MVP и MVVM называть MVC)

Не подумайте что я ярый фанат реакта, но из всех ангуляров и бекбонов он мне доставляет меньше всего боли при разработке сложных приложений (вспоминается цитата из выступления Александра Соловьева про FRP и кложуру «У меня уже все болит от этих чик-чик»). Но я все чаще смотрю в сторону FRP библиотек и языков.
… и передаете тип вызываемого редьюсера. Чтобы вызвать 3 редьюсера придется сделать 3 диспатча.

Это утверждение не верно. В Redux есть экшены, которые изначально являются простыми объектами с определенной структурой (Flux Standart Actions), который содержит в том числе тип экшена. Тип же это любая строка, циферка или что угодно, с чем мы сможем потом сравнить (а чтобы избежать ошибок — их выносят в отдельный файлик констант). И есть редюсеры, которые комбинируются с помощью combineReducers. То есть фактически редюсер всегд один, но может состоять из подмножества небольших редюсеров.

Что происходит во время диспатча — экшен прокидывается в этот самый единственный редюсер, а тот в свою очередь прокидывает экшен внутрь всех дочерних, каждый вовзвращает свой кусочек стейта и в итоге мы получаем новый стейт.
То есть, если не связывать тайпы с редюсерами, а чтобы тайп был фактом действия (как это рекомендует сам Дэн Абрамов), то получится что экшентайпы будут выглядеть, например, так:
COUNTER_TICK
API_REQUEST
MESSAGE_SENDED
MESSAGE_READED
и т.д.

При этом любой редюсер может реагировать на любой из экшенов. В примерах Redux-а это делается с помощью switch(action.type) {… } внутри любого из них.
Вернее будет сказать, что хочу чтобы различные редюсеры могли реагировать на одни и те же экшены :)
Это я понял.
Но в вашем примере получается, что все эти три компонента — прогрессбар, ошибка и данные юзера связаны между собой (смотрят в один кусок стейта). То есть их независимость, о которой я говорил, теряется.
В моем же примере ошибки могут приходить из любых других асинхронных запросов или даже вполне себе синхронных, например, форма не прошла валидацию, аналогично и с прогрессбаром.

п.с.
Минусы не мои :)
И конечно же тут на самом деле будут константы вместо магических экшн-тайпов и урлов :)
А компоненты, соответственно получают эти кусочки стейтов (с помощью селекторов / курсоров выдергивают только свои) и:
  • формочка показывает ошибки, если они есть или закрывается если есть юзердата
  • прогрессбар в данном случае просто крутилка, которая отображается пока длина массива больше 0
  • ошибки показываются, если есть что показать (в данном примере без удаления и проверок на актуальность)
На самом деле этот пример — упрощенный кейс из моей практики в текущем проекте, и он касался не логина. Но, если это поможет, то оформлю его в виде кода, максимально упростив (без проверок, иммутабельных состояний и прочих вещей, которые должны присутствовать) и, чтобы не углубляться в реализацию асинхронных запросов, заменю запрос экшеном с использованием redux-thunk, который делает диспатч FSA и второй диспатч по таймауту.

// actions
export const login = (username, password) => (dispatch) => {
  dispatch({
    type: 'API_REQUEST',
    payload: {
      uri: '/login',
      body: { username, password },
    },
  });

  setTimeout(
    () => dispatch({
      type: 'API_RESPONSE',
      payload: {
        uri: '/login',
        response: 401,
      },
      error: true,
    }
  ), 5000);
};

// users/reducer
export default (userState = {}, action) => {
  if (
    action.payload.uri === '/login' &&
    action.type === 'API_RESPONSE'
  ) {
    if (action.error) {
      return {
        error: 401,
      };
    }

    userState = action.payload.response;
  }

  return userState;
};

// progress/reducer
export default (progressState = [], action) => {
  if (action.type === 'API_REQUEST') {
    progressState.push(action.payload.uri);
  }
  if (action.type === 'API_RESPONSE') {
    const i = progressState.indexOf(action.payload.uri);
    progressState.splice(i, 1);
  }

  return progressState;
};

// errors/reducer
import { ERROR_MESSAGES } from './messages';
export default (errorsState = [], action) => {
  if (action.type === 'API_RESPONSE' && action.error) {
    errorsState.push({
      requestUri: action.payload.uri,
      message: ERROR_MESSAGES[action.payload.response],
    });
  }

  return errorsState;
};

// rootReducer
import users from '/users/reducer';
import progress from '/progress/reducer';
import errors from '/errors/reducer';

export default combineReducers({
  users,
  progress,
  errors,
});
По-моему тут возникает проблема зависимостей.

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

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

Если у нас отделены редюсеры от экшенов, то это легко реализовать, подписав каждый редюсер на нужные нам экшены: редюсер юзера (из стейта которого берет данные об ошибках формочка) ждет юзердату / ошибку в API_RESPONSE, прогрессбар положил в стейт данные на API_REQUEST и убрал их на API_RESPONSE, а редюсер ошибок положил ошибку, получив ее в API_RESPONSE.
Итого у нас три несвязанных компонента со своими стейтами и своей логикой, которые фактически слушают одни и те же события: два экшена.

В вашем же случае, как я понимаю, придется создать для каждого компонента отдельные экшено-редюсеры и явно комбинировать их в «мега экшене» (типа doMultipleActions). И мне почему-то кажется что в редкс-девтулз мы увидим, как задиспатчился этот самый «мега экшен», а тот в свою очередь задиспатчил еще несколько. Т.е. мы получаем более сложную хистори, которую в случае чего будет сложнее откатывать (если речь пойдет не про логин, а скажем про редактирование чего-нибудь с возможностью у юзера сделать анду).

Надеюсь я понятно изложил пример. Если я не прав, то поправьте меня. Спасибо.

Information

Rating
Does not participate
Location
Москва, Москва и Московская обл., Россия
Date of birth
Registered
Activity