• React-router пути не работают. Как вылечить?

    maxfarseer
    @maxfarseer
    https://maxpfrontend.ru, обучаю реакту и компании
    Очень похоже на ошибку с "выдачей скрипта", то есть
    scripts.js:1 Uncaught SyntaxError: Unexpected token <

    у вас там не script.js, а index.html отдается. Смотрите в network.
    Описано подробно в туториале по реакт-роутеру на русском
    Ответ написан
    2 комментария
  • Side Effects после исполнения reducer'a?

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

    Не совсем согласен. В action creators тоже можно практически безнаказанно провернуть какой-нибудь side-effect (сохранить токен в localStorage, например, после LOGIN_SUCCESS).
    Ответ написан
    Комментировать
  • React, redux, react-router, react-router-redux, как и где делать редирект после логина?

    maxfarseer
    @maxfarseer
    https://maxpfrontend.ru, обучаю реакту и компании
    Мыслите верно, делать dispatch REDIRECT стоит после dispatch SUCCESS_LOGIN.

    Судя по документации, в action creators (создатель действия, первый блок кода) вы все делаете правильно.

    Далее проверяйте у себя (я приведу код, похожий на ваш):

    1) в месте, где передаете history (обычно это Root/App компонент, то есть родитель всего)
    import { AppContainer } from 'react-hot-loader'
    import React from 'react'
    import ReactDOM from 'react-dom'
    import { Router, browserHistory } from 'react-router' // раз
    import { Provider } from 'react-redux'
    import { routes } from './routes'
    import { syncHistoryWithStore } from 'react-router-redux' //два
    import configureStore from './store/configureStore'
    
    const store = configureStore()
    
    const history = syncHistoryWithStore(browserHistory, store) //три
    const rootEl = document.getElementById('root')
    
    ReactDOM.render(
      <Provider store={store}>
        <AppContainer>
          <Router history={history} routes={routes} /> //четыре
        </AppContainer>
      </Provider>,
      rootEl
    )


    2) в месте, где настраиваете объект store (обычно, это функция configureStore)
    import { routerMiddleware } from 'react-router-redux' //раз
    import { browserHistory } from 'react-router' //два
    import { createStore, applyMiddleware, compose } from 'redux'
    import thunkMiddleware from 'redux-thunk'
    import createLogger from 'redux-logger'
    import { rootReducer } from '../reducers'
    
    export default function configureStore() {
      const store = compose(
        applyMiddleware(thunkMiddleware),
        applyMiddleware(createLogger()),
        applyMiddleware(routerMiddleware(browserHistory)), //три (!)
      )(createStore)(rootReducer)
    
      if (module.hot) {
        // Enable Webpack hot module replacement for reducers
        module.hot.accept('../reducers', () => {
          const nextRootReducer = require('../reducers').rootReducer
          store.replaceReducer(nextRootReducer)
        });
      }
    
      return store
    }


    3) combineReducers с роутингом (как у вас и написано)
    import { combineReducers } from 'redux'
    import { routerReducer } from 'react-router-redux' //раз
    import products from './products'
    import login from './login'
    import notificationBar from './notificationBar'
    import provider from './provider'
    
    export const rootReducer = combineReducers({
      products,
      login,
      notificationBar,
      provider,
      routing: routerReducer, //два
    })


    Из вашего вопроса информации недостаточно, но судя по всему вы либо:
    а) передаете не верный history в configureStore
    б) не выполнили syncHistoryWithStore (из пункта 1)

    --- дополнительно ---
    Как вариант посмотрите как сделать редирект после логина в redux с помощью middleware (упрощенный вариант, но хорошо для понимания основ)

    Так же есть "простой" вариант - хранить необходимые данные после логина (токен, свойства юзера, и т.д.) в localStorage. И после логина, делать стандартный browserHistory.push
    Ответ написан
    1 комментарий
  • Как исключить React модули из eslint?

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

    {
      "extends": "eslint:recommended",
      "parser": "babel-eslint",
      "env": {
        "browser": true,
        "node": true,
        "mocha": true
      },
      "plugins": [
        "react"
      ],
      "rules": {
        "no-debugger": 0,
        "no-console": 0,
        "no-case-declarations": 0,
        "new-cap": 0,
        "strict": 0,
        "no-underscore-dangle": 0,
        "no-use-before-define": 0,
        "eol-last": 0,
        "quotes": [2, "single"],
        "comma-dangle": [1, "always-multiline"],
        "jsx-quotes": [1, "prefer-single"],
        "react/jsx-no-undef": 2,
        "react/jsx-uses-react": 1,
        "react/jsx-uses-vars": 1
      }
    }
    Ответ написан
    1 комментарий
  • Как получить список друзей пользователя вконтакте?

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

    p.s. проверил запрос (из текста вопроса) в режиме инкогнито в хроме - все ок.
    Ответ написан
    Комментировать
  • Collection name must be a String?

    maxfarseer
    @maxfarseer
    https://maxpfrontend.ru, обучаю реакту и компании
    По вашему коду, не могу понять, что вы хотели сделать с помощью:
    var testdb = mongoose.model('testdb', testdbSchema, function(err){ ...

    Если вы хотели бы сохранить модель в базу, то судя по документации можно сделать это 2мя способами (адаптировал под ваши переменные):

    var testModel = mongoose.model('TestModel', testdbSchema);
    
    // способ 1
    var testRecord = new TestModel({ param: 100500 });
    testRecord.save(function (err) {
      if (err) return handleError(err);
      // saved!
    })
    
    // или способ 2
    TestModel.create({ param: 100500 }, function (err, small) {
      if (err) return handleError(err);
      // saved!
    })
    Ответ написан
  • Хорошо ли подходит NodeJS для парсинга сайтов?

    maxfarseer
    @maxfarseer
    https://maxpfrontend.ru, обучаю реакту и компании
    отлично подходит, как уже указано было выше - phantomjs очень крут!
    Ответ написан
    Комментировать
  • Верстали ли Вы используя React без какой либо логики?

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

    То есть, если у в компании четкое разделение, например на бэкэнд-девелопера (и он пишет на питоне) и на верстальщика (что само-собой разумеется), то бэкэнд-девелопер вполне может договориться + научить/объсянить верстальщику как использовать переменные и условия в шаблоне.

    Здесь ситуацию вижу подобную и думаю, что вполне реальна: вы хороший верстальщик и грамотно верстаете, а js-ниндзя сразу пишет логику не изменяя автозаменами все ваши class на className и так далее.
    Ответ написан
    Комментировать
  • Область видимости nodejs?

    maxfarseer
    @maxfarseer
    https://maxpfrontend.ru, обучаю реакту и компании
    Так у вас переменная db здесь не определена.
    То есть, если в config.js, например {param1: 'qweqwe', param2: 'ababaa'}, то в server.js должно быть
    var params = require('./config')
    либо
    var param1 = require('./config').param1
    Ответ написан
  • Как c помощью React-Router отправить картинку к API и получить ответ?

    maxfarseer
    @maxfarseer
    https://maxpfrontend.ru, обучаю реакту и компании
    Так как вижу в тегах redux - отвечу "в рамках" этого проекта.
    Вам нужно использовать action (действие) - "Отправка_картинки" (и это обычный асинхронный запрос, скорее всего это POST запрос, так?)
    А затем в ответе на ваш асинхронный запрос, генерировать событие "Картинка_отправлена" + данные ответа.
    В редьюсере, вы ловите событие "картинка_отправлена" и добавляете полученные данные в store.

    Причем тут роутер - неясно. Роутинг - это не работа с "урлами" вообще. Это лишь часть работы, так сказать. Грубо говоря, реакт-роутер решает, исходя из url-адреса - какой именно компонент(ы) вам показать.

    По работе с асинхронными действиями в redux можно почитать здесь.
    Ответ написан
    6 комментариев
  • Что делает EventEmitter в react.js?

    maxfarseer
    @maxfarseer
    https://maxpfrontend.ru, обучаю реакту и компании
    Он не то чтобы умеет, тоже что и в Node.js, он и есть 'events' из Node.js
    Ответ написан
    Комментировать
  • Как перейти на другую страницу в React?

    maxfarseer
    @maxfarseer
    https://maxpfrontend.ru, обучаю реакту и компании
    Здесь корректнее было бы сделать так:
    родительский компонент отрисовывает и таблицу и "страницу редактирования", причем у вас в сторе есть переменная, например: edit, если true -> отрисовывается "страница редактирования", если false - отрисовывается таблица.
    При нажатии на строку в таблице - генерируется action (действие), которое как раз в купе с прочими действиями (которые производятся у вас уже) изменяет edit
    Родительский компонент должен быть подписан на store.
    Ответ написан
    Комментировать
  • Как получить данные из Redux State?

    maxfarseer
    @maxfarseer
    https://maxpfrontend.ru, обучаю реакту и компании
    Если у вас есть данные в props - то просто отрисовывайте их в render функции (через this.props.filterState).
    Так как ваш компонент "присоединен" (с помощью connect), значит у вас всегда будут актуальные props.
    Props изменились - вызвается render (по логике работы react) => все отрисовано будет с актуальными данными.
    Ответ написан
    Комментировать
  • Правильно ли я понял суть Flux?

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

    На сколько я понимаю, flux работает по следующему принципу: view подписывается на изменения данных в sotre, если данные store изменились, то перерисовываем view

    Все верно поняли. Осталось лишь добавить, что изменения в store попадают с помощью ACTIONS - так называемых действий.

    p.s. из личного опыта - мне больше понравился redux, основное отличие которого от Flux - объект store всего лишь один! Внес свой вклад материалы на русском здесь.
    Ответ написан
    Комментировать
  • Какие преимущества/недостатки есть у HOC (Higher-order Components)?

    maxfarseer
    @maxfarseer
    https://maxpfrontend.ru, обучаю реакту и компании
    Добрый вечер.
    Обычно HOC делаются так, что "очередность" не важна.
    Обратиться из одного HOC к другому ... укажите задачу конкретную, мне кажется тут есть более простой способ.

    Преимущества (разберем это видео[EN]):
    мы описали "функциональность" и добавили ее с легкостью двум нашим компонентам. Следовательно, как минимум два отличных преимущества получили:
    + нет дублирования кода
    + простота в добавлении "функционала"

    Другой хороший пример - "Навигационная ссылка"[RU] (подраздел так и называется - Навигационная ссылка), опять же - мы дали функционал необходимый компоненту. Если этот функционал пригодится где-то еще - мы сможем это устроить.

    Почему порядок, скорее всего не важен - потому что обычно props передаются в стиле "бери все свойства" (...this.props), где ... - spread operator.

    Подытожим:
    используя HOC вы "не изменяете" компонент, который он получает, но добавляете при этом функциональность. Разве уже не круто?)
    Ответ написан
    2 комментария
  • Как понять Promise?

    maxfarseer
    @maxfarseer
    https://maxpfrontend.ru, обучаю реакту и компании
    Что есть "привязчик функции"?
    Вы на resolve и reject должны указать именно функции. Так как таким образом в аргументах у них будут необходимые данные. А таймер - хороший вариант "сфабриковать" асинхронное действие.

    Материал выбран хороший, прочитайте, поиграйтесь с примерами, потом посмотрите эту статью с хабра.

    Промисы нужно пощупать на практике, причем обязательно попробовать обработать ошибки:
    а) когда нет интернета
    б) когда ваше api ответило не "200"

    Затем попробуйте выполнить цепочки промисов (последовательно, параллельно).
    Смотрите в дебаггере по шагам, что за чем идет.

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

    maxfarseer
    @maxfarseer
    https://maxpfrontend.ru, обучаю реакту и компании
    В свое время, пока я делал сайты на joomla - я выкладывал свои работы на форумы по Joomla, и там было много отзывов/критики.
    Ищите такие же форумы по вашему основному языку и там ищите темы, например: мой сайт, мой проект и тд.
    Ответ написан
  • Есть ли курсы,скринкасты или учебники на русском по React js?

    maxfarseer
    @maxfarseer
    https://maxpfrontend.ru, обучаю реакту и компании
    Три курса:
    React.js на русском
    React + Redux на русском
    React + React-router (+ Redux) на русском

    Вся информация текстом, можно скачать в формате книги. Почти к каждой главе приложен исходный код.
    Ответ написан
    Комментировать
  • Express не грузит bundel.js React-а, что не так?

    maxfarseer
    @maxfarseer
    https://maxpfrontend.ru, обучаю реакту и компании
    У вас скорее всего указан неверный путь до файла. Подробнее здесь (весь раздел прочитайте, он короткий).
    Ответ написан
    1 комментарий
  • Как вернуть значение из Promise у Javascript?

    maxfarseer
    @maxfarseer
    https://maxpfrontend.ru, обучаю реакту и компании
    Отличная статья (хабр) на эту тему
    Ответ написан
    Комментировать