• React, redux, middleware какой набор инструментов и библиотек лучше использовать?

    maxfarseer
    @maxfarseer
    https://maxpfrontend.ru, обучаю реакту и компании
    с использованием разных библиотек для ajax запроса и это не считая jqwerry и middleware

    Про jquery, я так понимаю вы имеете ввиду $.ajax ? А вот про middleware... (может быть не до конца понимаете, что это такое?)

    По вопросам:
    1. Производительность
    А как в вашей сборке жмется конечный файл?
    сейчас собрал сборку gulp, browserify, babelify, babel + библиотеки redux и react

    Не увидел здесь uglifyJS или что-нибудь подобное...

    Многие собирают webpack'ом, (для продакшен версии используя флаг -p, который в свою очередь.. бинго! Запускает разные "сжималки" кода. Не буду вас путать, но по-моему там тоже uglifyjs)

    2. Стили
    Стили, это стили. Как вам нравится, так и пишите. Собирайте их хоть gulp'ом, хоть webpack'ом... Разницы нет.

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

    сегодня наткнулся на мануал использования webpack и gulp одновременно на одном проекте

    Оправдан. Если вам удобно какие-то таски прогонять через gulp, почему нет? Если сможете все, что делаете gulp'ом сделать на webpacke, то используйте только его.

    P.S. По поводу сборок. Брать чужую сборку обычно вредно (так как взяли, запустили, а коснись чего - неизвестно как это работает). Особенно, если сборка большая. Вот хороший пример большой и сложной "сборки". Чтобы понять как там все работает, потребуется порядком времени. А нужно ли будет вам все то, что автор туда накрутил? Поэтому, в качестве ознакомления, можно и посмотреть.

    P.P.S. Даже минимальная create-react-app сборка имеет немало всего интересного "под капотом". Поэтому, я за то, чтобы к сборке подходили осознанно, и лучше своей - придумать сложно. Опять же, "своя" появляется далеко не сразу, поэтому просто начните делать приложение.
    Ответ написан
    Комментировать
  • Как подключать сторонние react компоненты?

    maxfarseer
    @maxfarseer
    https://maxpfrontend.ru, обучаю реакту и компании
    Сложность в том, что архитектура react-проектов разная - в первую очередь, как мне кажется, связанная с redux.

    Как раз таки у "годных" компонентов (или может быть, кому-то ближе "плагинов") нет никакой привязки к тому, как у вас хранятся данные. Правило хорошего тона - ваш компонент, ничего не знает о том, что происходит вокруг, он просто отображает данные и вызывает функции обработчики, которые уже "где-то там" будут эти данные изменять. Считаю, что один самых крутых примеров такого компонента, это react-virtualized

    как можно их публиковать и загружать в проект?

    Так как, это npm пакет, то следовательно, нужно копать в эту сторону (пример). (гугл)
    Ответ написан
    Комментировать
  • Начальный шаблон express'a (что? где? куда?)?

    maxfarseer
    @maxfarseer
    https://maxpfrontend.ru, обучаю реакту и компании
    Ищите поиском по статье, которую вы привели в примере:
    Здесь будут жить все ваши макеты и файлы представления Jade.

    То есть, ваши шаблоны нужно класть в директорию views. В статье используется jade, поэтому посмотрите как работает этот шаблонизатор. Шаблон главной страницы, доступной по урлу mysite.com
    demo-app/views/index.jade

    Далее, как запустить, снова ищем поиском в статье:
    Это код, который позволяет вам запускать npm start для приложения.

    => для запуска, нужно выполнить в терминале:
    node ./bin/www

    или можно
    npm start
    Ответ написан
    2 комментария
  • Что за сопостовления в express?

    maxfarseer
    @maxfarseer
    https://maxpfrontend.ru, обучаю реакту и компании
    Это стадартный роутинг. Вы переходите по урлу, например mysite.com/abe или mysite.com/abcde , что сервер будет вам отдавать? Правильно, то что вы указали внутри "сопоставимого" роута, в случае этого примера, это ваш последний кейс:
    app.get('/ab(cd)?e', function(req, res) {
    res.send('ab(cd)?e'); // здесь может быть что-нибудь, например: покажи страницу с такой-то картинкой
    });
    Ответ написан
    1 комментарий
  • Как найти учителя JS и Node.js?

    maxfarseer
    @maxfarseer
    https://maxpfrontend.ru, обучаю реакту и компании
    В тему про codementor.io (ссылка, почему-то неправильно вставляется)
    https://www.codementor.io/experts?q=nodejs&lang=russian
    Ответ написан
    Комментировать
  • Как настроить sass в webpack?

    maxfarseer
    @maxfarseer
    https://maxpfrontend.ru, обучаю реакту и компании
    Ошибка вам явно говорит, что проблема тут:
    path = require('.');
    Я даже не знаю, валидный ли это код... будет ли он искать index.js в этом случае?) В любом случае, это вряд ли то, что вы хотели.

    (если речь про webpack 1)
    Вам нужен sass-loader и extract-text-plugin. Вот и небольшая статейка (EN).
    Ответ написан
    Комментировать
  • Библиотека асинхронных запросов для react?

    maxfarseer
    @maxfarseer
    https://maxpfrontend.ru, обучаю реакту и компании
    Тоже столкнулся с подобной проблемой, опишу как это в черновике выглядит у себя, но в целом пока красиво решено не было:

    Есть проект, на бэкэнде elixir+phoenix. Мне в каждом сообщении приходит ref + автоинкреметный id. Следовательно, когда я делаю первый запрос и данные идут долго, а потом второй запрос и данные приходят быстрее, то ref будет больше и я просто в редьюсере игнорирую старый ответ (в стиле, action.ref < state.ref => верни текущий стэйт).

    P.S. если используете сокеты, как вы "замедляете" получение ответа? Мне пришлось попросить "бэкэнд" отвечать медленнее, для тестирования этой проблемы. Так как в chrome devtools в нетворке "замедление" не работало для запросов по сокету.
    Ответ написан
    Комментировать
  • Как динамически добавить компонент в React?

    maxfarseer
    @maxfarseer
    https://maxpfrontend.ru, обучаю реакту и компании
    Google сразу выдает порядком вопросов, но в общем случае, если речь идет об однотипных компонентах, вот хороший ответ. Суть в нем сводится в том, что вы рендерите компоненты, на основе данных в state (это можеть бы так же и props, пришедшие из родителя..).

    (перевел главный кусок с ответа по ссылке выше)

    // ...
    // SampleComponent - ваш однотипный компонент
    // ...
    
    class Test extends Component {
        constructor(props) {
            super(props)
            this.addChild = this.addChild.bind(this)
            this.state = {
                components: [
                    {
                        id:1, name: 'Some Name'
                    }
                ]
            }
        }
    
        addChild() {
            // Изменение стейта спровоцирует перерисовку
            this.setState(this.state.concat([
                {id:2,name:"Another Name"}
            ]))
        }
        render() {
            return (
                <div>
                    <h1>App main component! </h1>
                    <button onClick={this.addChild}>Add component</button>
                    { // здесь будет отрисовано необходимое кол-во компонентов
                        this.state.components.map((item) => (
                            <SampleComponent key={item.id} name={item.name}/>
                        ))
                    }
                </div>
            );
        }
    }
    Ответ написан
    Комментировать
  • Нужен совет по react и angular?

    maxfarseer
    @maxfarseer
    https://maxpfrontend.ru, обучаю реакту и компании
    Что проще освоить новичку angular или react с redux-ом?

    Мое мнение: разницы нет

    Стоит ли переходить на angular или продолжить изучать react и redux?

    Если пишите, что понимаете angular лучше, то может тогда на нем уже стоит что-то сделать за деньги? По рынку вакансий - реакт догоняет ангуляр. Плюс в вакансиях по реакту конкуренция сейчас пониже (на мой взгляд).

    p.s. из вопроса, не понял каков уровень js... Что можете сделать на js (+ jquery и плагины?)
    Ответ написан
  • Nodejs/express + ES6 рекомендации?

    maxfarseer
    @maxfarseer
    https://maxpfrontend.ru, обучаю реакту и компании
    По первому пункту, ссылка от Антона в помощь.

    По второму вопросу: вы на node.js будете делать бэкэнд. Который будет являться API сервером, не более. Здесь придется поизучать что такое REST API. Следовательно, если вы будете писать фронтенд на react/redux, то кладете его в другую директорию, там уже свой package.json и т.д., так как ваш фронтенд и бэкэнд - это две разные вещи.
    Ответ написан
    Комментировать
  • Как в ReactJS организовать подключение компонента из другого файла?

    maxfarseer
    @maxfarseer
    https://maxpfrontend.ru, обучаю реакту и компании
    Вам нужно собирать бандл с помощью Wepback / Browserify и т.д. Require / import не сработают, даже если указать text/babel.

    Немного с SO:
    stackoverflow.com/a/36698789/1916578 (почему не работает require/import)
    stackoverflow.com/a/20578692/1916578 (на всякий случай, если вы не используете локальный сервер - здесь есть информация об ошибке и что с этими делать) + локальный сервер легко поднять с помощью http-server
    Ответ написан
    Комментировать
  • Используют ли при работе с Angular, Backbone, VUE и другими структуру из нескольких html-страниц?

    maxfarseer
    @maxfarseer
    https://maxpfrontend.ru, обучаю реакту и компании
    Не практикуют.
    Ответ написан
    Комментировать
  • Часто вижу в коде на сайтах сделанных на react такую конструкцию, что она значит?

    maxfarseer
    @maxfarseer
    https://maxpfrontend.ru, обучаю реакту и компании
    Это просто "продакшен" версия. В ней имена компонентов становятся такими.
    Попробуйте у себя сделать прод. сборку (например, с помощью wepback -p) и посмотрите, что получится.
    Ответ написан
  • Как правильно подключить React к сайту?

    maxfarseer
    @maxfarseer
    https://maxpfrontend.ru, обучаю реакту и компании
    В документации, один из пунктов, что нужно: A compiler such as Babel. It lets you write modern JavaScript code that still works in older browsers.

    Браузер "не умеет import", так сказать. Вам нужно прогонять ваши скрипты, написанные в ES2015 через инструменты, типа babel.
    Ответ написан
    Комментировать
  • Установка react/webpack, в чем проблема?

    maxfarseer
    @maxfarseer
    https://maxpfrontend.ru, обучаю реакту и компании
    Могу предположить, что возможно проблемы в пути (есть пробел у директории Study projects). Попробуйте провернуть все это в директории, в пути до которой нет пробелов.
    Ответ написан
  • Eslint Best practices?

    maxfarseer
    @maxfarseer
    https://maxpfrontend.ru, обучаю реакту и компании
    Во многих статьях вижу конфиг от airbnb, список правил тут

    В .eslintrc есть возможность "унаследовать конфиг". Например,

    {
      "extends": "eslint:recommended", // унаследовали от eslint:recommended
      ...
      "rules": { // переопределили/добавили свои правила
        "no-debugger": 0,
        "no-console": 0,
        ...
      }
    }
    Ответ написан
    Комментировать
  • Сортировка данных в react + redux?

    maxfarseer
    @maxfarseer
    https://maxpfrontend.ru, обучаю реакту и компании
    Можно нормализовать данные. По этому поводу, я думаю вам будет крайне полезно посмотреть второй курс[EN] от создателя redux.

    p.s. урок про нормализацию, где рассказывается, как можно решить вашу проблему, но мне кажется, чтобы понять, потребуется посмотреть весь курс.

    p.p.s. полезные ссылки:
    1) https://rajdee.gitbooks.io/redux-in-russian/conten... (может переведут, когда-нибудь)
    2) https://habrahabr.ru/company/hh/blog/310524/ (RU)
    Ответ написан
    1 комментарий
  • Как в React.JS сделать поочередный вывод из массива данных JSON?

    maxfarseer
    @maxfarseer
    https://maxpfrontend.ru, обучаю реакту и компании
    Вам нужно сделать API, которое будет отдавать определенное кол-во записей. Поясню: вам нужно сделать backend, так сказать. Можно написать на node.js / php / python / и т.д. Возможно, есть какой-то готовый сервис для подобных вещей, но я не искал.

    Например: GET запрос на api/loadjson?limit=100&offset=0 (выдай 100, отступ 0, потом будет запрос выдай 100 - отступ 100, выдай 100 отступ 200 и тд), т.е. в теории дело обстоит так: вы загружаете первые N записей и устанавливаете обработчик на window.onscroll (пример тут), далее выбираете через какой интервал в пикселях вы планируете подгружать еще и загружаете еще N записей и так далее.

    Подгрузку осуществляете с помощью xhr (или, если угодно - ajax) запросов (мне нравится isomorphic-fetch)

    Из готовых компонентов, рекомендую react-virtualized. Настройка сперва выглядит трудновато, но это одна из лучших библиотек в плане документации, которую я видел. Есть все! На всякий случай - gitter чат, где есть и сам разработчик (язык EN).
    Ответ написан
    5 комментариев
  • Как реализовать авторизацию пользователя на стеке React Redux Node?

    maxfarseer
    @maxfarseer
    https://maxpfrontend.ru, обучаю реакту и компании
    Пригодится jwt. (гугл)

    В общих словах: вам нужно выдать юзеру токен. С этим токеном юзер будет выполнять запросы к вашим защищенным методам api (вы можете оставить какие-то методы "без токена").

    Node.js часть
    Пример роута на логин (сделано не лучшим образом, в плане коллбэков, но что нашлось под рукой...):

    auth.js
    ...
    const v4 = require('node-uuid').v4
    const jwt = require('jsonwebtoken')
    ...
    router.post('/signin', (req, res, next) => {
    
      // валидация, например... 
    
      if (errors) {
        return res.status(400).json({ errors })
      } else {
        // поиск юзера в базе, сравнение хэша и прочие необходимые операции
        ...
       // допустим все ок, нужно ответить токеном
      // генерируем необходимые опции и сам токен
    
            const payload = {
              _id: user._id,
              iss: 'http://localhost:3000',
              permissions: 'poll',
            }
            const options = {
              expiresIn: '7d',
              jwtid: v4(),
            }
            const secret = new Buffer(process.env.AUTH0_CLIENT_SECRET, 'base64')
            jwt.sign(payload, secret, options, (err, token) => {
              // отвечаем токеном, для будущих запросов с клиента
              return res.json({ data: token })
            })
         ...
    })
    
    module.exports = router;


    Пример защищенного роута (метода, который требует токен):
    ...
    const jwt = require('jsonwebtoken')
    const Poll = require('../models/poll')
    ...
    
    const requireToken = (req,res,next) => {
      const token = req.headers['x-api-key']
      const secret = new Buffer(process.env.AUTH0_CLIENT_SECRET, 'base64')
    
      jwt.verify(token, secret, (err, decoded) => {
        if (err) {
          return res.status(401).json({ error: err.message })
        }
        req.params.userId = decoded._id
        next()
      })
    }
    ...
    
    // обратите внимание на requireToken - функция вызывается при каждом обращении к роуту
    // то есть при каждом PUT запросе по адресу (например: PUT api/v1/products/1238914)
    // будет вызываться requireToken
    
    router.put('/:id', requireToken, (req, res, next) => {
      const { productId } = req.body
      const userId = req.params.userId
    
      Poll.findById(req.params.id)
        .populate({ path: 'products' })
        .exec((err, poll) => {
            // ... необходимые действия в базе, в процессе успешного зачтения голоса...
        }
    })


    Клиентское приложение:

    Типичный ActionCreator (в качестве библиотеки для запросов можно взять bluebird, isomorphic-fetch, да хоть нативный xhr)
    actions/LoginActions.js

    export function login(data) {
      return dispatch => {
        dispatch({ type: LOGIN_REQUEST })
    
        // request в данном случае - https://github.com/KyleAMathews/superagent-bluebird-promise
        return request.post(`${API_ROOT_V1}/auth/signin`)
          .send(data)
          .then(res => {
            if (!res.ok) {
              dispatch({ type: LOGIN_FAILURE })
            } else {
              dispatch({
                type: LOGIN_SUCCESS,
                data: res.body.data,
              })
              //сохранение токена в localStorage
              localStorage.setItem('cks_token', res.body.data)
            }
          }, err => {
            dispatch({ type: LOGIN_FAILURE })
          })
      }
    }


    Пример голосования с токеном (выше, в node.js части был метод апи, а это PUT запрос с клиента)

    export function vote(productId, voteId) {
      return dispatch => {
        dispatch({ type: POLL_VOTE_REQUEST })
    
        return request.put(`${API_ROOT_V1}/api/v1/vote/${voteId}`)
          .set('X-API-Key', localStorage.getItem('cks_token')) // установка ТОКЕНА в заголовок 'X-API-Key'
          .send({ productId })
          .then(res => {
            if (!res.ok) {
              dispatch({ type: POLL_VOTE_FAILURE })
            } else {
              dispatch({
                type: POLL_VOTE_SUCCESS,
                data: normalize(res.body.data, schema.poll),
              })
            }
          }, err => {
            dispatch({ type: POLL_VOTE_FAILURE })
          })
      }
    }


    Надеюсь код формы с кнопкой "голосовать" не трубется.
    ====

    Все это можно организовать удобнее, например, выставлять токен всем запросам автоматически (речь про клиентскую часть):
    import fetch from 'isomorphic-fetch'
    ...
    const defaultHeaders = {
      Accept: 'application/json',
      'Content-Type': 'application/json',
    }
    
    function buildHeaders() {
      const authToken = localStorage.getItem('TOKEN')
      return { ...defaultHeaders, Authorization: authToken }
    }
    ...
    export function httpPost(url, data) {
      const body = JSON.stringify(data)
    
      return fetch(url, {
        method: 'post',
        headers: buildHeaders(),
        body: body,
      })
      .then(... код оработки запроса ...)
    }


    ===

    Проверить наличие токена, можно с в роутере, с помощью хука на onEnter.

    root.js
    ...
    <Provider store={store}>
          <Router history={routerHistory}>
            {configRoutes(store)} // Роуты создаются функцией, чтобы можно было использовать внутри нее store.getState()
          </Router>
        </Provider>
    ...


    routes.js
    export default function configRoutes(store) {
      function _ensureAuthenticated(nextState, replace, callback) {
        const { dispatch } = store
        const { session } = store.getState()
        const { currentUser } = session
        let nextUrl
    
        if (!currentUser && localStorage.getItem('cks.token')) {
          dispatch(getCurrentAccount())
        } else if (!localStorage.getItem('cks.token')) {
          replace('/signin')
        }
        callback()
      }
    
      return (
        <Route path='/' component={App}>
          <Route path='/signin' component={SigninContainer} />
          <Route path='/signup' component={SignupContainer} />
    
          <Route path='/locked' component={AuthenticatedContainer} onEnter={_ensureAuthenticated}>
            <Route component={LockedArea}>
              <Route path='/locked/a' component={A} />
              <Route path='/locked/b/:id' component={B} />
              <Route path='/locked/c' component={C} />
            </Route>
          </Route>
        </Route>
      )


    Остается только создать AuthenticatedContainer в котором проверять: есть ли currentUser (в рамках этого примера) и если нет - возвращать false. А если есть - this.props.children (в которых будут дальнейшие роуты..)
    ===

    Итого:
    1) у вас есть API написанное на node.js.
    2) У этого API есть защищенные методы, которые проверяют наличия токена в http-запросе. Токен выдается при запросе на логин. Само собой, операция логина (то есть POST запрос на your-api/login) не требует токена.
    3) После удачного логина, вы получаете в ответе на свой запрос токен (это уже внутри клиентского кода, и если мы говорим о redux - то внутри асинхронного вызова в actions)
    4) Сохраняете токен (например, в localStorage)
    5) Во все необходимые http-запросы устанавливаете заголовок с токеном
    Ответ написан
    15 комментариев
  • Как использовать jsx?

    maxfarseer
    @maxfarseer
    https://maxpfrontend.ru, обучаю реакту и компании
    Emmet поддерживается в JSX (sublime, например)
    Ответ написан
    4 комментария