Задать вопрос
  • Как вывести значение из функции при асинхронном запросе?

    rockon404
    @rockon404
    Frontend Developer
    Проблема в полном непонимании принципа работы асинхронного кода.
    Исправить можно так:
    const getUsers = () => fetch("https://jsonplaceholder.typicode.com/users");
    
    getUsers().then(res => res.json()).then(res => {
      document.getElementById("app").innerHTML = JSON.stringify(res);
    })
    Ответ написан
    Комментировать
  • Почему foo.x === undefined?

    rockon404
    @rockon404
    Frontend Developer
    Все достаточно просто, хоть и не совсем очевидно.
    Выражение:
    foo.x = foo = {n: 2};
    равносильно:
    foo.x = (foo = {n: 2});

    Мы присваиваем объекту по идентификатору foo свойство x, которое равно результату операции присваивания идентификатору foo ссылки на объект { n: 2 }.

    Чтобы в этом убедиться достаточно добавить переменную bar, присвоить ей начальное значение foo и вывести в конце:
    let foo = {};
    
    const bar = foo;
    
    foo.x = (foo = {n: 2});
    
    console.log(foo.x === undefined);  // true
    
    console.log(bar);  // { x: { n:  2 } }
    
    console.log(bar.x === foo);  // true


    Ключевые отличия операций присваивания, которые важно понимать:
    foo.x = - присваивание свойства конкретному объекту. На момент вызова в нашем примере это {}.
    foo = - присваивание значения самому идентификатору foo. Это может быть примитив, ссылка на объект или функцию. В нашем случае это объект { n: 2 }.
    Ответ написан
    Комментировать
  • Как вы решаете проблемы производительности React/Redux?

    maxfarseer
    @maxfarseer
    https://maxpfrontend.ru, обучаю реакту и компании
    Как вам правильно подсказали в комментарии - нужно профилировать.
    Для этого загружаетесь с панелью разработчика, нажимаете Profile и смотреть где у вас проблемы.

    Так же, легкий способ для начала - добавить console.log в рендер компонентов, и смотреть нет ли лишних перерисовок. Конечно, добавлять не нужно сразу везде, а можно постепенно покрывать (либо фичу, либо страницу, либо просто то - что кажется большим и ресурсоемким).

    Использование shouldComponentUpdate - один из самых распространенных и действенных способов.

    По вопросу: стало тормозить React/Redux-приложение - добавляйте больше конкретики, будет видно. Все индивидуально, но обычно самые простые советы - использовать SCU, дробить на мелкие компоненты, дробить данные для редьюсеров (не хранить все в одном большом), использовать селекторы, минимизировать выполнение трудных расчетов (может у вас где-то банально "тяжелая" функция постоянно пересчитывает результат, а это не нужно)

    p.s. неплохая статья на EN - https://medium.com/@alexandereardon/dragging-react...
    Ответ написан
    Комментировать
  • Почему render выполняеться перед componentWillMount?

    rockon404
    @rockon404 Куратор тега React
    Frontend Developer
    Потому что библиотека не ожидает возвращаемое значение в componentWillMount и следом сразу вызывает render.
    Забудьте этот метод - он не рекомендован к использованию. Как уже писали выше, асинхронные запросы рекомендуется инициировать в componentDidMount. Он выполняется после вызова render, который вы по какой-то неясной причине хотите избежать.

    Вот два варианта решения:
    1. До загрузки данных возвращать в render null или прелоадер.
    render() {
       const { data } = this.props;
    
       if (!data) return null;
         
        return (
          <div>
            <FilterModels />
          </div>
        )
      }
    }

    2. Переместить загрузку данных в родительский компонент и отрисовывать целевой по условию:
    render() {
      const { filterData } = this.props;
      return (
        <Wrapper>
          {filterData  && <FilterForm data={filterData} />}
       </Wrapper>
      )
    }
    Ответ написан
    Комментировать
  • Является ли хорошей практикой использовать setState в redux?

    rockon404
    @rockon404 Куратор тега React
    Frontend Developer
    По-хорошему в redux выносят только то, что используется в разных частях приложения, а так же данные полученные с сервера. Для остального предпочтительней использовать state компонента. В подавляющем большинстве случаев, lifting state up будет предпочтительней использования redux.

    Ответ Дэна Абрабомова на похожий вопрос How to choose between Redux's store and React's state.
    Ответ написан
    2 комментария
  • React + Redux, как записать в состояние после того как придут данные?

    rockon404
    @rockon404 Куратор тега React
    Frontend Developer
    static getDerivedStateFromProps(props, state) {
      if (props.visas[0] !== state.visa) {
        return {
          visa: props.visas[0],
        };
      }
    
      return null;
    }

    Массив this.props.visa должен существовать всегда.
    Ответ написан
    Комментировать
  • Как сделать экспорт в 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 комментария
  • Правильно я визуализировал работу под капотом в Redux+ReactRedux после Reducer?

    rockon404
    @rockon404 Куратор тега React
    Frontend Developer
    Все происходит совсем не так. Вы, видимо, пытаетесь угадать, а достаточно лишь изучить исходный код библиотеки react-redux и почитать про метод store.subscribe redux.

    redux и react-redux это две ничем не связанные и не подозревающие о существовании друг друга библиотеки. Компоненты react-redux лишь используют API объекта store из redux, который вы должны передать в Provider сами.
    Когда вы подключаете react-redux вы используете компонент Provider и HOC connect. Ниже перечислены их основные функции.

    Provider:
    1. Получает в props store и подписывается на его обновления с помощью store.subscribe.
    2. Инициирует перерисовку дочернего древа по обновлению store, с помощью вызова this.setState.
    3. Передает в контекст store и storeState(результат вызова store.getState())

    HOC connect:
    1. Передает нужные props в оборачиваемый компонент с помощью, полученного через контекст, состояния и маппера mapStateToProps.
    2. Оборачивает actions в вызов store.dispatch с помощью store, полученного через контекст, и маппера mapDispatchToProps, либо просто передает store.dispatch в props компонента как свойство dispatch.
    3. Если аргумент mapStateToProps был передан, то компонент-обертка, возвращенный вызовом connect, отслеживает обновления store. Если свойства полученные из store и props не были изменены, а компонент уже отрисован, то connect при обновлении возвращает сохраненный по ссылке отрисованный компонент, если изменения были, то дочерний компонент перерисовывается. Логику обновления можно понять, взглянув на функцию, результат вызова которой, вызывается в render компонента обертки:
    function makeChildElementSelector() {
      let lastChildProps, lastForwardRef, lastChildElement
    
      return function selectChildElement(childProps, forwardRef) {
        if (childProps !== lastChildProps || forwardRef !== lastForwardRef) {
          lastChildProps = childProps
          lastForwardRef = forwardRef
          lastChildElement = (
            <FinalWrappedComponent {...childProps} ref={forwardRef} />
          )
        }
    
        return lastChildElement
      }
    }


    Подробнее: react-redux with Dan Abramov
    Ответ написан
    Комментировать
  • Как правильно делать fetch в react?

    rockon404
    @rockon404 Куратор тега React
    Frontend Developer
    1. data.goals[0].gs_id
    Использование подобных, небезопасных конструкций считается плохим тоном.
    2. Используйте в state ключ состояния загрузки.
    export default class Forma extends React.Component {
        constructor(props) {
            super(props);
    
            this.state ={ data: {}, isFetching: true, error: null };
        }
    
        componentDidMount() {
            fetch('http://localhost:3001')
                .then(response => response.json())
                .then(result => this.setState({data: result, isFetching: false }));
                .catch(e => {
                  console.log(e);
                  this.setState({data: result, isFetching: false, error: e }));
                });
        }
    
        render() {
            const { data, isFetching, error } = this.state;
            
            if (isFetching) return <div>...Loading</div>;
    
            if (error) return <div>{`Error: ${e.message}`}</div>;
    
            return <h1>{data.goals[0].gs_id}</h1>;
        }
    
    
    }
    Ответ написан
    9 комментариев
  • Как обновить свой Fork репозитарий до последней редакции основного репазитария используя GitHub for Windows?

    CAXAline
    @CAXAline
    Перейти на вкладку Pull Requests
    Создаем новый реквест New pull request
    Пишет, что нечего сравнивать, но не расстраиваемся и жмем switching the base
    Появились отличия родительского и форкнутого проектов. Жмем Create pull request и даем ему название
    Автоматически оказываемся в этом пул реквесте и жмем Merge pull request
    И напоследок Confirm merge
    PROFIT
    Ответ написан
    2 комментария
  • Пример использования структурных шаблонов в React.js?

    miraage
    @miraage
    Старый прогер
    Декоратор. Многие HOC являются декораторами/прокси.

    Фасад. В мире React фасадами я бы назвал селекторы. Мы прячем комплексную структуру стора (причем, неважно, что используется - flux, redux, context, whatever) за простыми функциями-геттерами. Это могут быть как обычные геттеры, так и вычисляемые значения.

    Медиатор. Допустим, есть форма с двумя полями с датами "начало" и "конец". Первому нельзя ставить значение выше второго, и наоборот, второму нельзя поставить значение ниже первого. Тут и вступает в бой основной компонент формы, который является медиатором, и назначает разное поведение этим компонентам, в зависимости от их значений. Сами они друг про друга не знают.

    Обсервер. Тот же HOC connect из react-redux, по сути, является обсервером. Изменился mapState - ре-рендер компонента.

    Адаптер. Можно поверх сложных UI элементов (range, datepicker, etc..) писать еще свои адаптеры, которые будут иметь определенный программный интерфейс. Это позволит менять сторонние библиотеки (мало ли, автор забросит поддержку), сохранив при этом программный интерфейс внутри приложения.

    В самом React еще другие паттерны. Например, slot pattern, render props.
    Ответ написан
    Комментировать
  • Оценка своего уровня. Как улучшить код?

    rockon404
    @rockon404 Куратор тега React
    Frontend Developer
    1. Используйте const вместо let для определения переменных которые не переопределяются в коде. Это помогает снизить когнитивную нагрузку с человека читающего код и негласный стандарт в React разработке.

    2. Такие вещи как globalStyles и конфигурацию store лучше вынести в отдельные файлы. Они могут со временем хорошо разрастись.
    По поводу globalStyles, вы вообще можете вынести их в отдельный css файл.

    3. Вместо:
    {
      isModal
      ? <Route path="/auth" component={AuthPopup} />
      : null
    }

    лучше:
    {isModal && <Route path="/auth" component={AuthPopup} />}


    4. Вместо:
    function mapDispatchToProps(dispatch) {
        return {
            autoLogin: () => dispatch(autoLogin()),
            getBrowser: () => dispatch(getBrowser()),
            getMedia: () => dispatch(getMedia())
        }
    }


    лучше:
    const mapDispatchToProps = {
      autoLogin,
      getBrowser,
      getMedia,
    };


    5. Точки с запятыми в конце то есть, то нет. Определитесь и приведите код к одному виду.

    6.
    & label {}
    & input {}
    & span {}

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

    7. Почему папка со страницами называется Containers? Дань бойлерплейтам?

    8. Использование trailing comma является хорошей практикой.

    9.
    import {combineReducers} from 'redux';
    import photoReducer from './photoReducer';
    import authReducer from './authReducer';
    import globalReducer from './globalReducer';
    
    export default combineReducers({
        photoReducer, authReducer, globalReducer
    })


    Все таки приятней работать с хранилищем в котором ключи не имеют в названии слова reducer:
    import {combineReducers} from 'redux';
    import photo from './photoReducer';
    import auth from './authReducer';
    import global from './globalReducer';
    
    export default combineReducers({
      photo, 
      auth,
      global,
    });


    10. Забудьте вообще, что в языке есть возможность использовать вложенный тернарный оператор:
    return e === 'invalid-email' ? 'Неверно указан e-mail'
        : e === 'user-not-found' ? 'Указанный e-mail на найден'
        : e === 'wrong-password' ? 'Неверный пароль'
        : e === 'email-already-in-use' ? 'Указанный e-mail уже используется'
        : e === 'network-request-failed' ? 'Нет подключения к интернету'
        : e === 'operation-not-allowed' ? 'Произошла ошибка, попробуйте снова'
        : e === 'popup-closed-by-user' ? 'Окно авторизации закрыто пользователем'
        : e === 'account-exists-with-different-credential' ? 'Аккаунт уже существует с другими данными, используйте другой способ авторизации'
        : e

    Это одна из самых худших практик в JavaScript разработке. Тут лучше подойдет конструкция switch case

    11. Константы actionTypes лучше вынести в папку constants и разложить по разным файлам, иначе со временем у вас там будет свалка.

    12. Вместо:
    import {SET_ACTIVE, CHANGE_VALUE, SET_DEFAULT, UPLOAD, UPDATE_IMAGE, SET_IMAGE_ERROR, SET_LIKE, SET_COMMENT, ADD_ARTICLE_SUCCESS, FETCH_ARTICLES_START, FETCH_ARTICLES_SUCCESS, FETCH_ARTICLES_ERROR} from '../actions/actionTypes';

    Лучше:
    import {
      SET_ACTIVE,
      CHANGE_VALUE,
      SET_DEFAULT, UPLOAD,  
      UPDATE_IMAGE,
      SET_IMAGE_ERROR,
      SET_LIKE,
      SET_COMMENT,
      ADD_ARTICLE_SUCCESS,
      FETCH_ARTICLES_START,
      FETCH_ARTICLES_SUCCESS,
      FETCH_ARTICLES_ERROR,
    } from '../actions/actionTypes';


    13. Попробуйте внедрить библиотеку reselect. И для получения значения из store вместо записи вида:
    function mapStateToProps(state) {
        return {
            browser: state.globalReducer.browser
        }
    }


    использовать селектор:
    const mapStateToProps = state => ({
      browser: browserSelector(state),
    });
    Ответ написан
    12 комментариев
  • RESTful API и MVC — что это?

    Основной посыл использования RESTful API - применение основной идеи Паутины для взаимодействия автоматических агентов (приложений), а не только людей.
    Основная идея Паутины - построение распределенной информационной системы путем публикации неких абстрактных ресурсов, выдачи им идентификаторов (в сегодняшнем вебе - иерархических), определения ряда простых и широко известных операций над ними, не зависящих от содержимого ресурса (те самые GET, POST, PUT и т.д.), и связывания этих ресурсов ссылками (это называется гипермедиа, и в частности, гипертекст, если речь идет о текстовой информации).
    Как люди с появления Веба публикуют информацию в нем для потребления другими людьми, так и RESTful веб-сервисы публикуют иерархически структурированные ресурсы для потребления клиентами. Разница только в представлении - для людей это plaintext/HTML, для автоматических агентов - это JSON/XML/прочие форматы, которые удобно обрабатывать.
    Таким образом, если вы хотите какую-то информацию опубликовать как RESTful API, вам необходимо представить ее как набор ресурсов, а все операции над этой информацией выразить через набор предопределенных операций. Фишка в том, что во многих задачах этих предпопределенных операций вполне достаточно, главное правильно определить ресурсы.
    Важно понимать, что "ресурс" это обычно некоторая сущность, "существительное". Как правильно заметил Антон Жуков , ресурс /getItems хоть и может существовать в принципе, говорит о неудачно спроектированном API (действие представлено как ресурс).

    Есть и другие подходы к архитектуре распределенных приложений, например архитектуры, основанные на RPC (удаленный вызов процедур). Информация в таких архитектурах также представлена в виде некоторого набора сущностей, однако операции над ними определяются конкретной задачей, и для каждой сущности будет свой набор. Это больше соотвествует классическому ООП-подходу. Таким образом, RESTful следует подходу много сущностей (ресурсов) - мало операций (и эти операции известны заранее), а RPC - немного сущностей, но много операций над ними.

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

    Сама архитектура REST не привязана к конкретным технологиям и протоколам, но в реалиях современного Веб, построение RESTful API почти всегда подразумевает использование HTTP и каких-либо распространенных форматов представления ресурсов, например JSON, или, менее популярного сегодня, XML.

    Смысл использования REST в том, что принципы, хорошо показавшие себя в "человеческом" веб и позволившие построить самую большую распределенную ИС, применяют и для "веба машин".

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

    Vlad_IT
    @Vlad_IT
    Front-end разработчик
    1. Закомментированный код на гитхабе - не хорошо. https://github.com/marinarodkin/aviasales-app/blob...
    2. Минимум логики в render функции компонента. Все сложные конструкции переносите в методы, а лучше в отдельные компоненты (тогда сможете легче контролировать перерисовку компонентов через shouldComponentUpdate , чтобы они не перерисовывались, если данные не поменялись). Вы можете прямо как методы писать стрелочные функции:
      class Flight extends Component {
          getWeekDay = (date) => {
              //..
          }
          // ....
      }

    3. Вы в половине случаев используете точку с запятой, а в половине нет. Используйте чаще.
    4. Атрибут for нельзя использовать в jsx (как и class, как вы знаете). Вместо for пишите htmlFor
    5. Смотрите консоль инструментов разработчика, там есть ошибки.
    6. Освойте shouldComponentUpdate, он позволяет контролировать перерисовку компонента при изменении состояния или пропсов. У вас при изменении кол-во пересадок, перерисовывается весь список билетов, даже те, которые уже были в этом списке. Многие скажут, что еще рано такое учить, но я не согласен. Если не учиться контролировать перерисовку еще в начале обучения, то можно написать очень много тормознутого софта.
    7. У вас данные ticket.json подгружаются хардкодно из github, это не хорошо, т.к. этот файлик с данными есть в папке public, и если потенциальный работодатель захочет поменять там что-то, он не увидит изменений (т.к. грузится с гитхаба).
    8. У вас если в данных в параметре departure_date стоит 11.10.2018 (т.к. сегодня), то отобразится это как "11 окт 2018, вс", т.е. день недели неправильный. А он неправильный потому, что это не октябрь, а ноябрь. Ошибка в методе getDateFormat
      const newDate  = new Date (year, month, day, );
      const monthName = ["дек", "янв", "фев", "мар", "апр", "мая", "июня", "июля", "авг", "сент", "окт", "ноя", "дек"];
      const newMonth = monthName[newDate.getMonth()];

      конструктор Date вторым аргументом ожидает номер месяца, нумерация которого начинается с нуля. т.е. 0 - январь, 1 - февраль, 11 - декабрь. Судя по monthName вы подозвевали, что есть что-то неладное, но ошибись с реализацией. monthName должен иметь обычный вид, начинаться с января и заканчиваться декабрем, т.к. нулевой элемент массива как раз подходит по логике с нулевым месяцем. В getDateFormat, а также в getWeekDay, вычтите из month - 1
      const newDate = new Date(year, month - 1, day)
    9. У вас в тех же getDateFormat и getWeekDay в конструкторе Date вы в конце аргументов пишите запятую, так не нужно делать. Это не вредно и не полезно, просто дурной тон. Там в любом случае будет undefined, хоть с запятой хоть без нее.
    10. Картинки тоже грузятся с marinarodkin.github.io, измените.

    11. const getStopsNumber = (stop) =>{
            switch (stop) {
              case 3:
                return "3 пересадки"
              case 2:
                return "2 пересадки"
              case 1:
                return "1 пересадка"
              case 0:
                return "без пересадок"
              default:
                return // это не нужно делать, писать return. Если вы удалите эту (и строку выше), то результат будет такой же - undefined
            }
          }

    12. Если бы в SideBar пропс stopsData был не объектом, а строкой или числом, то компонент SideBar можно было бы безболезненно превратить в PureComponent. Ну это так, к слову об оптимизации.
    13. Я бы в stopsClick передавал не объект события e, из которого вы потом берете id элемента через e.target.id (что не есть гуд), а сделал бы стрелочную функцию (или bind), в которую бы передавал id. Вот так
      <input onClick={() => this.props.stopsClick("allStops")} />
      <input onClick={() => this.props.stopsClick("noStops")} />

      Если это читают опытные ReactJS разработчики, рассудите пожалуйста. Согласен, что на каждый компонент будет создана своя копия функции, но по крайней мере, не нужно взаимодействовать с DOM напрямую.
    14. Это не красиво
      if( this.state.stops.allStops === false && this.state.stops.noStops === true && this.state.stops.oneStop === true && this.state.stops.twoStop === true && this.state.stops.threeStop === true  ){
               newStops = {...this.state.stops, allStops: true}
          }

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


    Может я многое высосал из пальца, но это будет вам полезно. Учитесь, развивайтесь. Удачи вам в этом :-)
    Ответ написан
    1 комментарий
  • Нормальная ToogleButton на React. Как?

    rockon404
    @rockon404 Куратор тега React
    Frontend Developer
    Можно использовать нативный скрытый checkbox. Использовать его можно будет как контролируемый, так и как самостоятельный элемент. Слушать onChange или использовать ref. Стилизовать его можно под что угодно. Чтобы работало, надо обязательно использовать элемент label.
    Думаю, это самый универсальный и оптимальный вариант для этой задачи.
    Пример с использованием StyledComponents:
    spoiler
    import * as React from 'react';
    import styled from 'styled-components';
    
    
    const Wrapper = styled.label`
      position: relative;
      display: inline-block;
      width: 40px;
      height: 24px;
    `;
    
    const Input: any = styled.input`
      display: none;
    `;
    
    const Slider = styled.div`
      position: absolute;
      cursor: pointer;
      top: 0;
      left: 0;
      right: 0;
      bottom: 0;
      background-color: #ccc;
      transition: .2s;
      border-radius: 34px;
      
      &:before {
        position: absolute;
        content: "";
        height: 22px;
        width: 22px;
        left: 1px;
        bottom: 1px;
        background-color: white;
        transition: .2s;
        border-radius: 50%;
      }
      
      ${Input}:checked + & {
        background-color: ${props => props.theme.someColor1};
      }
      
      ${Input}:focus + & {
        box-shadow: 0 0 1px ${props => props.theme.someColor2};
      }
      
      ${Input}:checked + &:before {
        transform: translateX(16px);
      }
    `;
    
    interface Props = {
      name?: string
      checked?: boolean
      onChange?: Function
      innerRef?: Function
      className?: string
    }
    
    const ToggleSwitch = ({ innerRef, checked, onChange, className, name }: Props) => {
      return (
        <Wrapper className={className}>
          <Input 
            innerRef={innerRef}
            checked={checked}
            onChange={onChange}
            name={name}
            type="checkbox"
          />
          <Slider />
        </Wrapper>
      );
    }

    Ни одно свойство не является обязательным.
    Ответ написан
    Комментировать
  • В чем преимущества *nix, linux перед windows (для веб разработчика)?

    DevMan
    @DevMan
    1. вы получаете окружение близкое или идентичное к продакшену.
    2. вы получаете внятную консоль/шел из коробки.
    3. вы избавляетесь от массы вопросов типа "на локалке все работает, а залил на сервер и получил жопу" (или наоборот).
    4. у вас появляется более лучшее понимание как на сервере все работает.

    при теперешнем развитие технологий и производительности железа, нет необходимости себя ломать.
    можно попробовать в виртуалке (docker/vagrant)/дуалбуте и самому для себя решить стоит или нет.
    Ответ написан
    17 комментариев
  • Прокомментируете тестовое на react?

    rockon404
    @rockon404 Куратор тега React
    Frontend Developer
    1. Хотелось бы видеть в проекте использование redux. react+redux - это самый распространенный и востребованный стек в React разработке.

    2. Почему все хандлеры и состояния находятся в App, а не в Main? Как вы потом эту кашу собираетесь масштабировать? Переносите все, что связанно только с Main в Main. По-хорошему смотрите пункт 1.

    3. Слишком много функциональных компонентов. Подумайте их где можно заменить на классы с реализованным shouldComponentUpdate или на PureComponent, чтобы убрать лишние вызовы render этих компонентов.

    4. import Logo from 'images/Logo.png';
    называть пути к ресурсам с заглавной буквы неправильно.

    5. Вместо:
    const StyledLogo = styled.img.attrs({
      src: Logo,
      alt: 'Aviasales'
    })`
      width: 60px;
      height: 61px;
    `;

    Удобней в использовании:
    const StyledLogo = styled.img`
      width: 60px;
      height: 61px;
    `;

    и:
    <StyledLogo src={logo} alt="Aviasales" />

    6.
    const Error = ({ text }) => (
      <StyledError dangerouslySetInnerHTML={{__html: text}} />
    );

    зачем тут html?
    Для сохранения переносов строки есть css правило:
    white-space: pre-line;

    7. Вместо:
    let element;
    
    if (error && !isLoading) {
      element = <Error text={error} />;
    }
    if (!error && isLoading) {
      element = <Loader />;
    }
    if (!error && !isLoading) {
      element = (
        <>
        <Heading />
        <Main
        isCurrencyExchanging={isCurrencyExchanging}
        activeCurrency={activeCurrency}
        handleCurrencyChange={this.handleCurrencyChange}
        ticketsFilteredByStops={ticketsFilteredByStops}
        stops={stops}
        handleStopsChange={this.handleStopsChange}
        handleUncheckOther={this.handleUncheckOther}
        />
        </>
      );
    }
    return element;

    Лучше:
    if (isLoading) return <Loader />;
    
    if (error) return <Error text={error} />;
    
    return (
      <>
        <Heading />
        <Main
          isCurrencyExchanging={isCurrencyExchanging}
          activeCurrency={activeCurrency}
          handleCurrencyChange={this.handleCurrencyChange}
          ticketsFilteredByStops={ticketsFilteredByStops}
          stops={stops}
          handleStopsChange={this.handleStopsChange}
          handleUncheckOther={this.handleUncheckOther}
        />
      </>
    );


    8. Вместо:
    filterTickets = (tickets, stops) => {
      return tickets.filter((ticket) => {
        return values(stops).indexOf(ticket.stops) !== -1;
      });
    };

    Лучше:
    filterTickets = (tickets, stops) => tickets.filter(
      ticket => values(stops).includes(ticket.stops),
    );


    9. Не пропускайте отступы между методами и между вложенными свойствами css.

    10. Вместо:
    componentsDidMount() {
      // много кода
    }


    Лучше:
    componentsDidMount() {
      this.fetchSomeData();
    }


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

    12. Loader и Error самое место в директории components/core или что-то вроде того. Там же, по-хорошему, должны находиться базовые компоненты: кнопки, инпуты, табы, чекбоксы.

    13. Styled компоненты, имхо, лучше писать в файле с компонентом, где они применяются. Так анализ кода происходит гораздо быстрей и легче поддерживать. Исключение - переиспользуемые компоненты.
    Даже если вам больше нравится выносить, называть файл style неправильно, вы там описываете компоненты, а не просто стили.
    Ответ написан
    3 комментария
  • Как наследовать стили в Styled Components?

    rockon404
    @rockon404 Куратор тега React
    Frontend Developer
    Если хотите изменить стили React.Component надо передавать методе render свойство className. Так же можно вынести все элементы компонента в статические поля, чтобы позже переопределять их стили.
    const Wrapper = styled.div`
      // some styles
    `;
    
    const ChildElement = styled.div`
      // some styles
    `;
    
    class MyComponent extends React.Component {
      static ChildElement = ChildElement;
      
      render() {
        const { className } = this.props;
    
        return (
          <Wrapper className={className}>
            <ChildElement>Some text</ChildElement>
          </Wrapper>
        )
      }
    }
    
    export default MyComponent;


    const SyledMyComponent = styled(MyComponent)`
      // some styles
    
      ${MyComponent.ChildElement} {
        // some styles for ChildElement
      }
    `;


    Метод extend работает только со StyledComponent:
    const AbstractElement = styled.div`
      // some styles
    `;
    
    const ConcreteElement = AbstractElement.extend`
      // some styles
    `;
    Ответ написан
    6 комментариев
  • Запуск анимации только когда человек доскролил?

    lastuniverse
    @lastuniverse
    Всегда вокруг да около IT тем
    Вот вариант без сторонних библиотек. Для просмотра демки перейдите во вкладку [Result] и покрутите на нем колесико мышки вверх и вниз.

    Ответ написан
    7 комментариев