Ответы пользователя по тегу Redux
  • Как заставить реакт рисовать компонент с нуля?

    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 комментариев
  • Что такое 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 комментария
  • С чего и где начать обучению React, Redux?

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

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

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

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

    Во-первых - onClick={this.updateClick('params')} - что вы ожидаете от такой записи? Давайте поразмышляем: в onClick вы должны передать функцию-обработчик, а вы передаете РЕЗУЛЬТАТ функции this.updateClick так как вызываете ее с ( )

    Во-вторых, как вам правильно подсказали, можно использовать .bind для передачи параметров.
    Для этого, сначала идем в MDN, читаем. Пытаемся передать функцию с параметром в качестве домашнего задания. Подсказка: .bind ставит ваши параметры в начало. То есть все аргументы сдвигаются (в том числе и "e").

    P.S. Если не получится, то можете посмотреть ответ по ссылке.

    P.P.S. Очень важно понять, что есть результат работы функции. То есть, в вашем вопросе, вы передавали в onClick - e.preventDefault(), причем именно это, а не "функцию, которая по клику бы срабатывала и происходил бы e.preventDefault()). В случае с bind, вы передаете результат работы функции bind, который является функцией, другими словами - "все корректно, в onClick передается функция".
    Ответ написан
    Комментировать
  • Как в componentWillMount получить params router?

    maxfarseer
    @maxfarseer
    https://maxpfrontend.ru, обучаю реакту и компании
    в роутере должно быть:
    ...
    <Route path='/signin/:название_параметра' component={Компонент} />
    ...


    в компоненте внутри componentWillMount вызывать this.props.params.название_параметра
    Ответ написан
    4 комментария
  • Как настроить роутинг?

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

    Не могу точнее ответить на вопрос без кода запуска сервера и возможно пригодится еще код webpac-dev-server и webpack-config файлов.
    Ответ написан
    1 комментарий
  • Почему не видит state?

    maxfarseer
    @maxfarseer
    https://maxpfrontend.ru, обучаю реакту и компании
    Давайте по порядку:
    1) this не видит, потому что у стрелочной функции нет своего контекста (пример, учебник)

    2) прокидывать this в mapDispatchToProps не нужно. Если вы хотите изменить state опираясь на новые данные, то это нужно делать в componentWillReceiveProps методе.

    3) чтобы пришли новые props, вам нужно их обработать в редьюсере, а для этого вам нужно вызывать в mapDispatchToProps ваш экшен-крейтор. То есть mapDispatchToProps будет выглядеть так (обратите внимание на круглые скобки после => , это сделано, чтобы не писать rerturn {...}):
    const mapDispatchToProps = (dispatch) => ({
      fetchEntities: (limit, offset) => dispatch(fetchEntities(limit, offset))
    })


    для этого, конечно же импортировать из actions ваш fetchEntities. В котором у вас promise версия, в которой будете обрабатывать пришедшие данные. Теория по этому поводу здесь, либо можете посмотреть теорию+пример на русском языке здесь.

    3.5) В mapStateToProps у вас должно быть соответствующее свойство, в которое вы будете из reducer'a прокидывать ваши новые props, и из-за этого сработает componentWillReceiveProps внутри которого вы сможете вызывать this.setState.
    Ответ написан
    9 комментариев
  • Как сделать обработку ошибок через axios последний?

    maxfarseer
    @maxfarseer
    https://maxpfrontend.ru, обучаю реакту и компании
    А зачем через Promise? У вас обычный синхронный код проверки и все. Пусть будет:
    ...
    router.post('/', (req, res) => {
        const {errors, isValid} = validateInput(req.body);
    
        if(!isValid) {
            return res.status(400).json(errors);
        } else {
            return res.status(200).json({data: 'bla-bla-bla'})
        }
    });
    ...


    Ну а сам axios заранее "промисифицированный". Взял пример из документации:

    axios.post('/user', {
        firstName: 'Fred',
        lastName: 'Flintstone'
      })
      .then(function (response) {
        console.log(response);
      })
      .catch(function (error) {
        console.log(error);
      });


    Если я вас правильно понял, то вы хотели бы использовать then/catch у axios, но думаете, что если роутер экспресса не возвращает promise - это невозможно? Нет, это не так.

    Если вернет ошибку - выполнится catch, если вернет "ок" - выполнится then. Не могу сказать по памяти, но res.status(400) может сработать как then, потому что вернуто не "ошибочное" значение. Тогда просто вместо res.status(400) бросьте исключение (типа new Error ...) и тогда точно catch сработает.
    Ответ написан
    4 комментария
  • Как правильно структурировать архитектуру приложения?

    maxfarseer
    @maxfarseer
    https://maxpfrontend.ru, обучаю реакту и компании
    Если вы не хотите сравнивать props с помощью shouldComponentUpdate (пишете, что это не резонно), то я думаю единственный вариант - делать компоненты Filter и List контейнерами (Operations по-желанию, из задачи не понятно, хочется его тоже "не обновлять" или нет)
    Ответ написан
  • В каком виде лучше хранить данные в store?

    maxfarseer
    @maxfarseer
    https://maxpfrontend.ru, обучаю реакту и компании
    Добрый день! Ваш вопрос очень хорошо разбирается во втором курсе на egghead от создателя Redux. Конкретно, один из самых близких к вашему вопросу ответ - https://egghead.io/lessons/javascript-redux-normal... (используется normalizr).

    Но мой ответ, к вам не сколько в видео про "нормалайзер", а про то, что посмотрите весь курс и вы познакомитесь с такой темой, как селекторы. То есть, будете вытаскивать в компонентах только нужные данные с помощью определенных функций селекторов, которые опишете в ваших редьюсерах. У вас получится как минимум на 1 уровень глубже использовать combineReducers для того, чтобы держать:
    а) массив id-шек
    б) объект с ключами, в виде id ваших записей (объект объектов, так сказать)

    Говорю это опираясь на свой опыт. После перехода на "массив с id" + "объект объектов" + селекторы => проблема указанная в вопросе исчезает!

    Привожу скриншот из проекта, над которым сейчас работаю: (на странице рендерится список поставщиков)
    bf23114aea41409386f2d583a8d78567.png

    P.S. этот вопрос будет подробно разобран в новом туториале, но боюсь он выйдет не раньше конца лета.
    Ответ написан
  • Как использовать Redux в Meteorjs, если там много коллекций?

    maxfarseer
    @maxfarseer
    https://maxpfrontend.ru, обучаю реакту и компании
    Я так понимаю, нужно коллекцию подписывать на изменение в store. Дробить store на кусочки (кусочек для каждой коллекции) + использовать combineReducers. Бегло посмотрел вот этот материал (на англ.)
    Ответ написан
    Комментировать
  • Redux и MobX - плюсы и минусы, когда лучше что использовать?

    maxfarseer
    @maxfarseer
    https://maxpfrontend.ru, обучаю реакту и компании
    Сразу скажу - не использовал MobX, но если вы читаете дальше - значит интересуетесь.
    Ответ про плюсы redux для меня лично - в самом конце.
    ---
    До React, писал на angular, и еще раньше на backbone. В ангуляр разработке у меня были места, которые я для себя объяснял: ок, так работает ангуляр (дайджест там, скоуп такой хитрый и т.д.) - факт был в том, что не все было прозрачно для меня лично.

    Начал разбираться с React и переписал часть рабочего проекта на React + Flux. В целом понравилось, но немного напрягало копирование однотипного кода. Появился redux, который (это важно) решил мою проблему. Все, тут я сделал остановку. Написал еще пару внутренних проектов - понравилось. Меня не напрягает ничего. Все уместно, код читается хорошо. Если я возвращаюсь к старому проекту - я очень быстро вникаю в "как это работает" и могу приступить к решению задачи.

    В процессе работы с Redux - появился Graph QL. Клево! Опять что-то новенькое - начал разбираться, и закрыл - так как быстро въехать не получилось, и попутно мне пришла простая мысль: зачем? Меня устраивает то, как работает связка React + Redux. Поэтому, я не стал вникать в saga, и пока что не хочется вникать в MobX. Возможно, это не правильно, ведь я их даже не смотрел, но свободное время от "вникания в новую технологию" я потратил на "дебри" технологий, которые активно использую.

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

    Главные плюсы redux для меня:
    + Если не трогал проект больше месяца - очень легко вспомнить что к чему.
    + Я пишу код. Я не вникаю в новое, я наращиваю знания по "старому" => я пишу быстро
    + Удобно тестировать

    Когда использовать:
    - когда хотите сделать одностраничное (SPA) приложение с нуля
    - когда хотите постепенно перевести старый проект на схему: вьюха (вся страница, или какой-то блок) + API запросы
    Ответ написан
    2 комментария
  • Как оптимизировать mapDispatchToProps?

    maxfarseer
    @maxfarseer
    https://maxpfrontend.ru, обучаю реакту и компании
    Есть хороший вариант: подключить actions через *

    import * as UserActions from '../actions/UserActions'
    ...
    const mapDispatchToProps = (dispatch) => {
      return {
        userActions: bindActionCreators(UserActions, dispatch)
      }
    }


    В таком случае, все действия юзера (а именно, все экспортируемые функции из файла UserActions) будут доступны из this.props.userActions (например, this.props.userActions.saveUser)

    Так же, можно не писать return, если вы возвращаете объект (как раз наш случай)
    const mapDispatchToProps = (dispatch) => ({
      userActions: bindActionCreators(UserActions, dispatch)
    })


    Обратите внимание на круглые скобки.
    Ответ написан
  • Какие основные понятия в архитектурах Flux, Reflux, Redux?

    maxfarseer
    @maxfarseer
    https://maxpfrontend.ru, обучаю реакту и компании
    в redux у вас есть:
    store - состояние всего приложения в одном(!) объекте. Для удобства, вы конечно бьете "store" на кусочки и изменяете/обновляете его не целиком, но в конечном счете объект store все равно один.
    actions - действия. Все изменения в redux приложении делаются действиями. Например: Действие(тип: ДОБАВИТЬ_ОДИН)
    actions creators* - создатели действий. Функции, которые вы можете вызывать, вместо того, чтобы вызвать действие, напрямую. Например:
    function add() {
      return { тип: ДОБАВИТЬ_ОДИН }
    }

    reducer - редьюсер. Функция которая принимает текущий объект store, и возвращает новый (с новыми данными).

    Итого: в redux фундаментальных понятий всего три: действие (action), редьюсер (reducer) и состояние (store)

    В реакте и того меньше: есть одно понятие - компонент. А уж там, если хочется: умный/тупой компонент, stateless компонент и может быть что-то еще.

    p.s. в коде функций присутствует русский язык для наглядности.

    p.p.s. туториалы: react для начинающих, создание приложения с использованием redux
    Ответ написан
    2 комментария
  • Автоматизация тестирования ractjs/redux enzym + mocha, с чего начать?

    maxfarseer
    @maxfarseer
    https://maxpfrontend.ru, обучаю реакту и компании
    Начать с unit-тестов для редьюсера и создателей действий. Хорошо описано на 1й странице документации - redux.js.org/docs/recipes/WritingTests.html

    По тестированию интерфейса - не силен в этом, но enzym выглядит очень круто, даже лучше чем стандартные реактовские утилиты для тестирования.

    Еще недавно вышла Hypernova

    P.S. вы бы вопросику еще тэг "react" поставили, было бы больше просмотров. Я и не знал, что есть на тостере тэг redux.
    Ответ написан
    Комментировать
  • 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 комментарий
  • Как c помощью React-Router отправить картинку к API и получить ответ?

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

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

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

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

    1. Произвести аутентификацию
    2. Сохранить токен в компонент
    3. Делать запрос с токеном пользователя.

    Пункт 3 можно улучшить, например не подсвечивать кнопку сделать запрос без токена.
    Ответ написан