• Почему при добавлении атрибута type выдает ошибку в консоли о невозможности загрузки файла app?

    maxfarseer
    @maxfarseer
    https://maxpfrontend.ru, обучаю реакту и компании
    Возможно, chrome не хочет открывать по пути file:// файл с непонятным типом.
    Как вариант, если взять код отсюда, то можете просто запустить локально сервер командой node server.js и открыть в хроме адрес localhost:3000 - будет работать.
    Ответ написан
  • Как правильно установить nvm на os x?

    maxfarseer
    @maxfarseer
    https://maxpfrontend.ru, обучаю реакту и компании
    Мне помогло полное удаление NVM и node.js. Далее порядок: установить NVM, после этого установить node.js через NVM.

    Пост про удаление node.js stackoverflow.com/a/11178106/1916578
    Ответ написан
    1 комментарий
  • Как можно переключить страницу исползуя React Router после получения данных?

    maxfarseer
    @maxfarseer
    https://maxpfrontend.ru, обучаю реакту и компании
    Можете решить прелоадером. Пока нет данных - рисуете прелоадер (строку "загружаю...", часики, или что еще).
    Ответ написан
    1 комментарий
  • Могут ли возникнуть проблемы при внедрении React в приложение использующее Zurb Foundation или UI Semantic?

    maxfarseer
    @maxfarseer
    https://maxpfrontend.ru, обучаю реакту и компании
    Не могут.
    Сможете спокойно внедрять react-код для необходимых "кусков" (зон с данными, или не знаю как еще назвать, областей?) на странице.
    Ответ написан
    Комментировать
  • React, Router и Аутентификация. Как лучше реализовать?

    maxfarseer
    @maxfarseer
    https://maxpfrontend.ru, обучаю реакту и компании
    Задачу можно разделить на 2 части:

    1) получение токена (идентификатора сессии или что еще нужно) от сервиса.
    2) onEnter хук в роутере

    Примерный код:
    export default function configRoutes(store) {
      function _ensureAuthenticated(nextState, replace, callback) {
        const { dispatch } = store 
        const { session } = store.getState()
        const { currentUser } = session
    
        if (!currentUser && localStorage.getItem('token')) {
          dispatch(getCurrentAccount())
        } else if (!localStorage.getItem('token')) {
          replace('/signin')
        }
    
        callback()
      }
    
      return (
        <Route component={App}>
          <Route path='/signin' component={SigninContainer} />
          <Route path='/signup' component={SignupContainer} />
    
          <Route path='/' component={AuthenticatedContainer} onEnter={_ensureAuthenticated}>
            <Route component={ReportContainer}>
              <Route path='/activities' component={ActivitiesContainer} />
              <Route path='/activities/:id' component={CaptionsContainer} />
            </Route>
          </Route>
    
        </Route>
      )
    }


    Более подробно можно посмотреть в источнике. ConfigRoutes функция вызывается здесь.
    Ответ написан
    Комментировать
  • ReactJS + Electron. В чем ошибка?

    maxfarseer
    @maxfarseer
    https://maxpfrontend.ru, обучаю реакту и компании
    Судя по ошибке, babel не может преобразавать "react-компонент" и для него "<" (22:2 - первый символ в строке <Provider... , а так же если вы убирали , то первый символ в<App...) - это не валидный код.

    Добавьте в файлик с настройками пресет "react", (или создайте с подобным содержимым)

    .babelrc
    {
      "presets": ["es2015", "stage-0", "react"],
    }
    Ответ написан
    Комментировать
  • Где найти человека способного быстро и качественно научить основам JS за деньги?

    maxfarseer
    @maxfarseer
    https://maxpfrontend.ru, обучаю реакту и компании
    Есть codementor.io , там можно отсортировать по "русский" и "javascript", например. Потом думаю сможете договориться работать без системы.

    p.s. в целом сложно найти ментора. Обычно два пути: платить больше чем человек получает по ставке в час на "подработках", либо пройтись по знакомым разработчикам, которые смогут порекомендовать кого-нибудь (но тут неизвестно, насколько хорош или плох уровень будет)
    Ответ написан
    5 комментариев
  • React.js. Сайт целиком на реакте или применять реакт модульно?

    maxfarseer
    @maxfarseer
    https://maxpfrontend.ru, обучаю реакту и компании
    В свое время "подсел" на реакт, потому что он позволял переделывать "кусочки" продукта, а не все целиком. Это нравилось и заказчикам (меньше рисков, быстрее) и мне.

    У вас получается, главный плюс если все будет на react - 100% SPA, которое потом можно показать как проект в портфолио в данной тематике. Особенно стоит задуматься о веб-приложении полностью на реакте, если интересует подобная работа в будущем.

    Не малый плюс, что в случае с React вам будет нужно написать API и потом это же API можно будет использовать в мобильном приложении(?)

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

    Какие цели у проекта? От этого и нужно отталкиваться. Если цель - опробовать бизнес-модель, то лучше просто сделать быстрее. Если цель научиться - делайте на том стэке, знания о котором хотите повысить.
    Ответ написан
    3 комментария
  • Как перенести часть строки на новую строку в свойстве компонента?

    maxfarseer
    @maxfarseer
    https://maxpfrontend.ru, обучаю реакту и компании
    Возможно поможет dangerouslySetInnerHTML

    Пример использования есть в туториале (поиском по странице "rawMarkup")
    Ответ написан
    Комментировать
  • Пробрасывание функций из actions через дерево компонентов vs connect функций в компоненте?

    maxfarseer
    @maxfarseer
    https://maxpfrontend.ru, обучаю реакту и компании
    Добрый день.

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

    Мне нравится connect, все устраивает.

    В записи для connect (а точнее для mapDispatchToProps) использую или не использую bindActionCreators:
    const mapDispatchToProps = (dispatch) => ({
      pollActions: bindActionCreators(PollActions, dispatch),
    })


    const mapDispatchToProps = (dispatch) => ({
      getUsers: (params) => dispatch(getUsers(params)),
      dispatch,
    })


    P.S. покажите пример с пробрасыванием функций из actions через дерево компонентов, и если уже что-то интересное для себя в этом подходе выделили - напишите. Будем смотреть вместе.
    Ответ написан
  • Как в Reac Router программно поменять путь?

    maxfarseer
    @maxfarseer
    https://maxpfrontend.ru, обучаю реакту и компании
    Путаница в вопросе:
    1) как программно поменять путь?
    2) как с помощью RR показать второй компонент через 10 сек?

    То есть, вам нужно изменять роут, например через 10 секунд? (таким образом компонент, принадлежащий этому роуту будет показан).

    Программно изменить роут можно с помощью push, replace (там же). Там же есть примеры, один из них.
    Ответ написан
  • Как заставить реакт рисовать компонент с нуля?

    maxfarseer
    @maxfarseer
    https://maxpfrontend.ru, обучаю реакту и компании
    В reducer'e заводите переменную, например isFetching с состоянием true/false в моменты выполнения асинхронного запроса (true на REQUEST, false на SUCCESS).

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

    ...
    render()
    ...
      if (this.props.isFetching) {
        <p> Loading...</p>
      } else {
        <p> {ВАШИ_ДАННЫЕ} </p>
      }
    Ответ написан
    7 комментариев
  • Как подключить handlebars в .hbs шаблон?

    maxfarseer
    @maxfarseer
    https://maxpfrontend.ru, обучаю реакту и компании
    А вы используете express? Если да, то вам нужен express-handlebars
    Так же нужно установить в качестве "шаблонизатора" - handlebars.
    app.engine('handlebars', exphbs({defaultLayout: 'main'}));
    app.set('view engine', 'hbs'); //в офф.доке используют расширение handlebars
    Ответ написан
  • Почему могут не отображаться компоненты в react developer tools?

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

    это как?)

    Если я правильно понял вопрос, вы хотите чтобы были нормальные имена у компонентов? Тогда вам просто нужно использовать не продакшен версию (скорее всего не .min файл, если вы с CDN грузите).
    Ответ написан
    1 комментарий
  • Модульность на фронтенде?

    maxfarseer
    @maxfarseer
    https://maxpfrontend.ru, обучаю реакту и компании
    (кратко про себя)
    Все лежит в папках: компонент + стиль. Собирается webpack'ом. Но у меня react-проекты.

    (длинно, но вроде бы по делу)
    Если относительно долго занимаетесь - у вас скорее всего уже выработались части, которые похожи - их выносите. Так же скорее всего у вас есть одинаковая структура (обычно это js/css/images и html, либо как вы пишите компонентами (отдельными папками) внутри котороых html + стили и может js ). Делайте шаблон для будущих проектов, в первую очередь удобным для себя - ведь вам с ним работать, а в нем реализуйте то что умеете по-максимуму (жмите картинки, оптимизируйте js и т.д)

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

    кажется, что не использовал это все на 100%

    Всем так кажется, поэтому когда не хочется заниматься работой, идем в гугл и смотрим опен-сорс проекты других людей: gulp, wepback, затем если нашли что-то любопытное идем в npm/github читаем доку. Пытаемся применить в работе.

    Что имеем в итоге?
    1) если все работает и вас устраивает (скорость сборки, удобство проверки в разных браузерах ...) - "работу работать";
    2) если есть время и желание - гуглите опен-сорс решения, читайте твиттер интересных людей / новостную подписку;
    3) если хочется услышать мнение коллег, но при этом коллег рядом нет - пишите статью на хабр. Просто статья: я использую такие-то плагины в своем "шаблоне" - вряд ли получит лестные отзывы, но возможно кто-то напишет: вот в этом месте у вас плохо, сделайте иначе. Возможно, вы придумаете, как написать статью интересно - тогда честь и хвала. И критика. А обоснованная критика всегда хорошо.

    P.S. если используете Jade и следуете BEM-методологии, то я бы порекомендовал посмотреть на этот проект
    Ответ написан
    Комментировать
  • Что такое API в проекте на react?

    maxfarseer
    @maxfarseer
    https://maxpfrontend.ru, обучаю реакту и компании
    У вас приведено 2 куска кода из 2х разных миров:
    1) это код из мира фронтенда, в котором вы выполняете запрос на /api/user/
    2) это код из мира бэкэнда, в котором вы обрабатываете роут ???/user (почему ???, потому что не видно главного файла сервера, но если представить, что вы разбираете какой-то рабочий пример, скорее всего это и есть обработчик /api/user роута)

    API (wikipedia)

    Как это завязать на API

    1. Делается сервер (на любом из языков), который в принципе является набором роутов, например:
    GET на роут /products - отдает все продукты
     POST на роут /products/add - создает новый продукт
     GET на роут /proudcts/1231rh8fdf - отдает один продукт с id 1231rh8fdf
     DELETE ...
     PUT ...

    2. Пишется клиент, если в рамках реакт-редукса, то главное в вашем вопросе, это то что вы уже привели - запросы на определенный роут в action creator.
    Например:
    export function signIn(email, password) {
      return dispatch => {
    
        dispatch({
          type: USER_SIGN_IN_REQUEST,
        })
    
        const data = {
          session: {
            email,
            password,
          },
        }
    
        httpPost(`http://${API_ROOT_V1}/api/sessions`, data)
          .then((data) => {
            dispatch({
              type: USER_SIGN_IN_SUCCESS,
              data: data.account,
            })
          })
          .catch((err) => {
            console.warn(`Sign in error: ${err}`) //eslint-disable-line no-console
            dispatch({
              type: USER_SIGN_IN_FAILURE,
              err,
            })
          })
      }
    }

    Этот action creator (создатель действий) делает POST запрос на API-сервер (можно и так называть сервер в частном порядке) вместе с логином и паролем. Далее сервер обрабатывает этот запрос (то есть ищет совпадение роута и метода (get/post/put..) и выполняет необходимые операции, после этого выдает ответ (например, json с данными о юзере) и вы эти данные устанавливаете в ваш reducer.

    Все что вам нужно, это действительно, разобраться что же такое API и с чем его едят. Конкретных статей на это, к сожалению, дать не могу. Может быть кто-то подскажет дельные.

    Итого: что такое API в проекте на React - вопрос не корректный. Правильный вопрос: как вы взаимодействуете с API в приложениях написанных на react, либо: как написать API на языке ХХХ (пример на англ для node.js и express - https://scotch.io/tutorials/build-a-restful-api-us...
    Ответ написан
    Комментировать
  • Где найти модуль авториации, регистрации redux?

    maxfarseer
    @maxfarseer
    https://maxpfrontend.ru, обучаю реакту и компании
    Опираясь на то, что вам не подошел ответ с Auth0

    Что в таком случае "модуль авторизации/регистрации"? Здесь вопрос поставлен не верно может быть?.
    Изначально, если мы говорим про Auth0 - это подходит под слово модуль (бэкэнд + готовые формочки, которые они дают вместе с примерами).

    Если же мы говорим про задачу frontend-разработчика, то она звучит так:
    1) Сверстай формы (включая валидацию и что еще нужно, например disabled для кнопки, если не заполнено обязательное поле)
    2) По клику на кнопку "войти" / "зарегистриоваться" - отправляй POST запрос с данными.
    2.5) Так как у вас приложение на React+Redux, значит необходимо создать action creator, который диспатчит, что-то в стиле USER_SIGN_IN_REQUEST (SUCCESS), и reducer для хранения инфы о юзере (если нужно).

    На этом кончаются задачи фронтэндщика.

    А то решений сейчас много и не знаю какое выбрать

    Скиньте пример, потому что я не понимаю о каких "решениях" идет речь, так как вижу ответом на ваш вопрос: две формы + стандартный набор для react-redux приложения.

    P.S. возможно вы имели ввиду под модулем, что-то в стиле форма + войти через соц.сеть/сервис - тогда да, я вас понял, но подсказать готовый не могу.
    Ответ написан
    4 комментария
  • Почему не всегда срабатывает e.target.dataset?

    maxfarseer
    @maxfarseer
    https://maxpfrontend.ru, обучаю реакту и компании
    У вас клик на ссылке, а data-* на элементе <i>
    Когда кликаете по ссылке - e.target = ссылка и у нее нет data-*
    Когда в клике попадаете на i = все хорошо.
    Ответ написан
    3 комментария
  • Как правильно организовать авторизацию веб-сервиса на Express?

    maxfarseer
    @maxfarseer
    https://maxpfrontend.ru, обучаю реакту и компании
    Как на счет jwt ?

    За! Удобно, нравится.

    Вкратце - шлете стандартные регистрационные данные, сервер выдает вам токен. Далее токен добавляете в заголовки запросов.

    В прицнипе, в гугле инфы хватает по вопросу. Сам сайт посмотрите (jwt.io), оттуда ссылка на пакет для node

    Скопирую сюда куски кода из своего api сервера, но скажу сразу - в node я не очень силен, если будут замечания от знающих - только рад. Так же angular кода не приведу, потому что клиентский код у меня на react.

    Здесь в файле используются callbacks, возможно есть варианты получше. В других роутах приложения я где-то через async поигрался, где-то через promise.

    Мой роутер auth

    const express = require('express')
    const router = express.Router()
    const User = require('../models/user')
    const v4 = require('node-uuid').v4
    const jwt = require('jsonwebtoken')
    
    router.post('/signup', (req, res, next) => {
    
      req.check('email', 'Please enter a valid email').len(1).isEmail()
      req.check('password', 'Please enter a password with a length between 4 and 34 digits').len(4, 34)
    
      const errors = req.validationErrors()
    
      if (errors) {
        return res.status(400).json({ errors })
      } else {
        User.hashPassword(req.body.password, (err, passwordHash) => {
          if (err) {
            return res.status(400).json({ error: err.message })
          }
    
          const user = new User({
            name: req.body.name,
            nickname: req.body.nickname,
            email: req.body.email,
            password: req.body.password,
          })
    
          user.passwordHash = passwordHash
          user.save((err, item) => {
            if (err) {
              return res.status(400).json({ error: err.message })
            }
            const payload = {
              _id: item._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 })
            })
          })
        })
      }
    })
    
    router.post('/signin', (req, res, next) => {
    
      req.check('email', 'Please enter a valid email').len(1).isEmail()
      req.check('password', 'Please enter a password with a length between 4 and 34 digits').len(4, 34)
    
      const errors = req.validationErrors()
      const password = req.body.password
    
      if (errors) {
        return res.status(400).json({ errors })
      } else {
        User.findOne({ email: req.body.email }, (err, user) => {
          if (err) {
            return res.status(400).json({ error: err.message })
          }
          if (!user) {
            return res.status(400).json({ error: 'User not found' })
          }
          User.comparePasswordAndHash(password, user.passwordHash, (err, areEqual) => {
            if (err) {
              return res.status(400).json({ error: err.message })
            }
            if (!areEqual) {
              return res.status(400).json({ error: 'Wrong password' })
            }
            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;


    Модель user

    const mongoose = require('mongoose')
    const bcrypt = require('bcrypt')
    const Schema = mongoose.Schema
    let bcrypt_cost = 12
    
    const userSchema = new Schema({
      name: { type: String, required: true },
      email: { type: String, required: true },
      passwordHash: String,
    })
    
    userSchema.statics.hashPassword = (passwordRaw, cb) => {
      if (process.env.NODE_ENV === 'test') {
        bcrypt_cost = 1
      }
      bcrypt.hash(passwordRaw, bcrypt_cost, cb)
    }
    
    userSchema.statics.comparePasswordAndHash = (password, passwordHash, cb) => {
      bcrypt.compare(password, passwordHash, cb)
    }
    
    const User = mongoose.model('User', userSchema)
    
    module.exports = User


    В коде роутера есть AUTHO_CLIENT - так как я изначально брал реализацию от AUTH0, кстати, может понравится? У них удобно все... Но для себя в целях обучения переписал на свою. (какая-то ссылка у них про angular cookies vs token)

    Мне нравится, что некоторую информацию я могу взять прямо из токена (например, уровень доступа - в моем примере - poll)
    Ответ написан
  • С чего и где начать обучению React, Redux?

    maxfarseer
    @maxfarseer
    https://maxpfrontend.ru, обучаю реакту и компании
    Присоединяюсь к Михаилу - язык нужен. В тех ссылках что он вам скинул - Dan (автор и видео и самого redux) говорит достаточно понятно.

    Я по весне писал объемный redux туториал , там react 0.14 (но он очень близок к 15) и остальные пакеты "постарее", но вы можете брать его за основу, а пакеты ставить новые. Единственное, тогда еще не было курса №2 из другого ответа, поэтому я не использовал "селекторы". Но это не помешает вам погрузиться в мир redux.

    P.S. курс по react тоже есть.
    Ответ написан
    2 комментария