Ответы пользователя по тегу Redux
  • Для чего нужны imutable данные в React?

    maxfarseer
    @maxfarseer
    https://maxpfrontend.ru, обучаю реакту и компании
    Нет профита, не заморачивайтесь.
    Когда "профит" от immutable будет маячить на горизонте, вы уже будете к этому готовы (либо столкнетесь с какой-то проблемой и выйдете на иммутейбл, либо просто повысите теоретическую базу / сложность задачи). Насколько я понимаю, с использованием immutable и без использования .toJS() - поиск в структуре ваших данных будет производиться быстрее.

    p.s. если найду видео добавлю, там была презентация. пока не нашлось.
    Ответ написан
    Комментировать
  • Как добавить поле в Record в immutable.js?

    maxfarseer
    @maxfarseer
    https://maxpfrontend.ru, обучаю реакту и компании
    case ADD_PRODUCT_TO_CART_SUCCESS: {
      return state.setIn(["entities", payload.productUid], {...payload.product, count:  ВАШЕ_КОЛИЧЕСТВО});
    }

    В этом коде мы берем все что было в payload.product и по 1 полю добавляем в новый объект ( фигурные скобочки = новый объект), а так же добавляем поле count. Количество (count) вы так же, наверняка, будете передавать в экшене. Получится: count: payload.count (или как вы назовете поле в вашем экшене...)

    Пример:
    { type: ADD_PRODUCT_TO_CART_SUCCESS,
        payload: { productUid, product, count: ваше_количество } // сюда count можно передавать из функции с помощью которой ваш экшен был создан...
      }
    Ответ написан
    2 комментария
  • Что такое side эффект?

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

    Пример: есть у вас в localStorage имя пользователя. И вы в коде пишите, что-нибудь такое:
    case SET_DISPLAY_NAME: {
      return {
        ...state,
        name: window.localStorage.getItem('name') ? window.localStorage.getItem('name') : action.payload,
      }
    }


    Следовательно, если вы подадите на вход функции, имя Вася, то оно вам вернет Васю только если "в sideeffect локал_сторадже" нет ничего. Здесь вы не можете быть уверены, что если подать Васю, вам всегда вернется Вася.

    По примеру с комментариями - не думаю что хороший пример. Айдишники генерировать будет бэкэнд ваш. Вы добавляете новый комментарий путем отправки его на сервер, с сервера приходит статус "ОК" и ваш комментарий уже с айдишником.

    Бывает, что айдишники нужно генерировать самому, тогда они отлично генерятся в acftionCreator'ax. Например, делаете вы систему уведомлений, и у каждого уведомления должен быть свой id (например, тут сервер вам не нужен, вы ничего туда не отправляете, просто визуальная часть). В таком случае, я бы не стал генерировать id через middleware, а просто делал бы это в "экшенах".

    Тем не менее, с генерацией айди все тоже самое, что и с localStorage. Вы не уверены, что подав на вход: имя, текст комментария и почту - получите ТОТ же результат, что и в прошлый раз с такими же входными параметрами (айдишники то разные будут!)
    Ответ написан
    3 комментария
  • Как в React сделать динамическую подгрузку контента?

    maxfarseer
    @maxfarseer
    https://maxpfrontend.ru, обучаю реакту и компании
    Если вы рисуете новые данные через .map и внутри map у вас отрисовывается компонент, то:
    а) написать компонент в functional (stateless) стиле
    б) написать компонент через наследование класса от React.PureComponent
    в) добавить shouldComponentUpdate

    В таком случае у вас будут дорисовываться только ново-пришедшие данные в комонент-родитель.

    Если у вас внутри map сразу верстка, то сделайте компонент и затем на выбор а/б/в выше.

    Документация
    Ответ написан
    1 комментарий
  • Как добавить пользователей в firebase?

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

    Посмотреть как в firebase получить всех пользователей и в нужный момент, выполнять запрос за ними.
    Или тут больше вопрос о том чтобы найти в firebase API нужный метод?
    Ответ написан
    4 комментария
  • React + Redux, как создать выпадающий список?

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

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

    Итого: получаем данные от севера, кладем их в соответствующий редьюсер, по щелчку изменяем стейт компонента и показываем/скрываем список, по клику в списке (если такое нужно) - отправляем экшен, который улетает на сервер, и, допустим, сохраняет измененную инфу о юзере - приходит ответ - вы далее сами решаете, класть этот ответ снова в reducer и как-то заставлять на это реагировать UI или нет.

    Когда идет речь, об "отправляем экшен" - это значит из компонента-представления мы вызываем метод (через функцию переданную в качестве пропса) родителя, то есть компоненета-контейнера. В контейнере этот метод должен в итоге вызывать (или сразу быть так передан) "приконекченный" вызов ( внутри функции connect, в качестве аргумента mapDispatchToProps). Если совсем "в наглую делать" для теста, то это store.dispatch.ACTION_CREATOR_NAME

    const UserContainer = connect(
      state => ({
        default_role: state.customerProject.default_role,
        show_role: state.customerProject.show_role,
        roles_user: state.customerProject.roles_user
        
      }),
      dispatch => ({
        anyName: () => dispatch(myActionCreator()) // и затем this.props.myNewActionCreator нужно передать в компонент-представление. Если нужно сделать доп-обработку, то передать метод из контейнера, в котором будет сначала обработка, а потом вызов this.props.myNewActionCreator
      }))(AboutUser)
    ...
    
    const changeRoleUser = () => {
            this.props.anyName()
        }
    ...
    Ответ написан
  • В чем разница между Redux и Reflux?

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

    Технически: обе библиотеки берут свое начало от реализации flux, но имеют разницу в деталях. Судя по документации reflux - у них тоже (как и flux) несколько store-хранилищ. У redux - store един.

    Суть библиотек одна: однонаправленный поток управления данными. Если говорить простым языком: как управлять всеми данными в приложении: кто-то куда-то кликнул, что-то где-то изменилось.
    Ответ написан
    Комментировать
  • Как написать тест для валидации, react/redux?

    maxfarseer
    @maxfarseer
    https://maxpfrontend.ru, обучаю реакту и компании
    Подкину теории: вы хотите протестировать функцию. Ваша функция чистая ( то есть выдает один и тот же результат для одних и тех же входных параметров, иначе _аргументов_ функции). Следовательно тестировать такую функцию просто.
    А) вы импортируете функцию в своем файле с тестами
    Б1) вызываете ее без values.value - ожидаете, что errors.value = 'Please enter value'
    Б2) вызываете ее с values.value === props.initialValues.value и ождаете, что будет errors.value = 'Please enter a new value'

    то есть, вы сами описываете в первом it вашего теста объект values, во втором it описываете values и props. Ваш тест можно описать так: "вы предполагаете, что если дадите 20 рублей продавцу, он выдаст вам батон". Тут так же: вы предполагаете, что если функция validate получит такие-то аргументы (только что вами в этом тесте созданные) - получится такой-то ответ от нее.

    const validate = require('./validate');
    const values = {} // то есть values.value - не существует
    const props = {} // для первого теста на существование значения, нам не важно какие тут значения props
    test('покажет ошибку, если нет значения', () => {
      expect(validate(values, props)).toBe('Please enter value');
    });


    Второй тест вам на домашнее задание.

    p.s. я писал в ответе it, потому что привык, что тесты пишутся внутри it, но сейчас в доке jest вижу, что они используют test ...
    Ответ написан
    3 комментария
  • React + Redux: какие преимущества в раздельном подключении каждого контейнера через connect?

    maxfarseer
    @maxfarseer
    https://maxpfrontend.ru, обучаю реакту и компании
    первый вопрос:
    при изменениях в store (глобальном state) у вас будут перерисовываться все компоненты, которые подписаны на эти изменения и в которых нет явного запрета на это через shouldComponentUpdate. То есть, если перерисуется родитель, то потом перерисуются и все его потомки. Класс? (сарказм, разумеется не класс). Поэтому подключение в "субконтейнерах", как вы говорите - продуктивнее: будут перерисовываться только те кусочки (родитель+дети), которые были подписаны на кусок (часть) данных из глобального store.

    второй вопрос: так работает react-redux библиотека и частности функция connect, которая словно "приклеивает" ваши выборочные данные из store в props приконнекченного компонента. (используются возможности свойства рекакт компонентов - context ). Через react dev tools посмотрите, и увидите, что у вас автоматически, в результате работы функции connect, появляется родитель Conneceted(ComponentName) в котором оказываются нужные свойства (через контекст) и которые прокидываются вниз в ребенка (в уже написанный вручную вами компонент) пропсы.
    Ответ написан
    Комментировать
  • Как оргаизовать logout у пользователя?

    maxfarseer
    @maxfarseer
    https://maxpfrontend.ru, обучаю реакту и компании
    export const logout = () => {
      sessionStorage.removeItem('auth');
      return {}; <-- забыли экшен свой { type: LOGOUT }
    };
    Ответ написан
  • Как дать команду на ре-рендер после добавления элемента в firebase?

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

    Далее, когда вам приходить событие в стиле: в_базу_добавился_новый_элемент вы должны вызвать action, который будет обновлять у вас в сторе ваши данные. Таким образом, если тут все правильно приготовить, то у вас в компонент придут новые пропсы и он перерисуется.

    То есть, здесь совсем не понадобятся методы жизненного цикла у компонентов (разве что, componentWillReceiveProps в будущем, но пока точно без него можно сделать).
    Ответ написан
    Комментировать
  • Как обновить запись в массиве без изменения порядка (Immutable)?

    maxfarseer
    @maxfarseer
    https://maxpfrontend.ru, обучаю реакту и компании
    Читаем документацию: update
    Смотрим пример:
    const list = List([ 'a', 'b', 'c' ])
    const result = list.update(2, val => val.toUpperCase())
    // List [ "a", "b", "C" ]


    Почему не работает данный кусок - потому что immutable.
    Ответ написан
    Комментировать
  • Как правильно обновить комонент в react + redux?

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

    В вашем случае, нужно через экшен из Х что-то изменять в том редьюсере, на который подписан ваш ChangeMe.

    > нужно добавить проверку в компоненте ChangeMe не изменились ли параметры
    lifecycle метод componentWillReceiveProps вам поможет

    > но есть ситуации когда его нужно обновить даже когда парамерты не изменились
    эту ситуацию описать внутри componentWillReceiveProps в обычном if условии.
    Ответ написан
  • Как в React + Redux обмениваться данными между компонентами?

    maxfarseer
    @maxfarseer
    https://maxpfrontend.ru, обучаю реакту и компании
    Как в React + Redux обмениваться данными между компонентами?

    Обмен данными происходит через один общий объект состояния store.
    Вам нужно "приконнектить" оба компонента с помощью:
    connect(mapStateToProps, mapDispatchToProps)(ComponentName)

    и тогда они у вас будут слушать изменения в сторе (за счет, того, что вы передадите в функции mapStateToProps), а так же смогут уметь передавать изменения в стор (с помощью dispatch функции, которую вы будете вызывать внутри mapDispatchToProps).

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

    Если немного упростить, то вам нужно будет:
    из компонента Settings вызвать action creator (через dispatch)
    в компоненте User это дело поймать (поймаете с помощью редьюсера, на который будет "натравлена" функция mapStateToProps)
    Ответ написан
    1 комментарий
  • Redux-Store Best practice: как лучше в store разделять данные от состояния UI?

    maxfarseer
    @maxfarseer
    https://maxpfrontend.ru, обучаю реакту и компании
    Состояние интерфейса обычно хранится в state компонента.
    - экраны в связке с роутингом (тут и состояние хранить обычно не нужно дополнительно, так как оно уже хранится в роуте (объект location))
    Ответ написан
  • Как прокинуть данные из promise(axios) в state redux?

    maxfarseer
    @maxfarseer
    https://maxpfrontend.ru, обучаю реакту и компании
    Конкретно в вашем примере, вы можете просто сохранить ссылку на this или использовать любые другие варианты привязки/проброса контекста...
    const that = this
    that.props...

    Но это вредный(!!!) совет. Так как скорее всего вы что-то делаете "не по учебнику". В componentDidMount у вас должен быть вызов action creator'a, внутри которого будет вызываться axios и из then которого вы будете dispatch'ить событие.

    p.s. не забывайте про подключенный redux-thunk, иначе вам придется dispatch импортировать в свои экшены, что тоже будет не по учебнику ;)
    Ответ написан
  • Как перенести большой проект на react 16?

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

    Заодно можете настроить prettier и прогнать все файлы под единый стиль (если еще нет).
    Тоже самое про eslint (можно в процессе переписывания заодно исправить все ошибки).

    p.s. попробуйте автоматические "тулзы", может прокатит.
    Ответ написан
    Комментировать
  • Как правильно удалять нужный элемент из массива?

    maxfarseer
    @maxfarseer
    https://maxpfrontend.ru, обучаю реакту и компании
    Так как вам всегда нужно возвращать новый массив, задачу можно разделить следующим образом:
    1) в новый массив копируете* все с начала до index
    2) в этот же новый массив копируете все с index+1 до конца

    * - для копирования отлично подходит spread operator. В теории выглядит так:
    const arr = [{a:1},{b:2},{c:3},{d:4}]
    //допустим, вы прислали index 1 и сохранили его в переменную index, например
    const newArr = [
      ...arr.slice(0, index), // клонируем все элементы до индекса
      ...arr.slice(index+1), // клонируем все элементы после индекса
      // итого: индексный элемент удален
    ]


    Хазрат Гаджикеримов вам верно подсказал так же про filter. В комментарии привел верное решение. Давайте теперь рассмотрим ваше:
    if(action.type === 'REMOVE_STUDENT') {
            let newArr = state; // сохранили в newArr ссылку(!!!) на старый массив. Если вы хотели скопировать массив, то нужно было писать: let newARr = [...state] (если в state просто массив)
            newArr.splice(action.payload, 1); // здесь вы из newArr ( и из state, так как сохранили ссылку) удалили с ИНДЕКСА один элемент. Так же, внимание, вы используете sPlice, а не slice. Разницу нужно уточнить! (подсказка ниже как)
            return newArr.filter(element => element !== action.payload); // а здесь вы что вообще написали? вы сравнили element (что там? объект?) с action.payload (в которой как вы говорите индекс). Что должно быть в итоге? ;)
        }


    Очень легко гуглить все незнакомые функции по типу: name MDN
    в вашем случае запросы в гугл:
    slice MDN (первая ссылка выдачи)
    filter MDN (первая ссылка выдачи)

    Теория из-за которой не происходит понимания: копирование объектов по ссылке
    Ответ написан
    2 комментария
  • Где найти примеры очень сложных работ на Javascript/React/Angular/Vue?

    maxfarseer
    @maxfarseer
    https://maxpfrontend.ru, обучаю реакту и компании
    А кто, собственно, захочет выкладывать в опен-сорс решения для коммерческих организаций? Это же занимает время. Нужно все приготовить, подчистить, задокументировать где не хватает, тесты дописать. Это куча работы, кому за это заплатят? Какой прок от этого организации (повышение доверия к организации - как вариант, но далеко не всем это нужно)? Придется объяснять, что это за продукт, и что он делает. Почему применены такие-то костыли и как с этим жить. Бррр... там работы много. Не нужной для организации работы.

    Так же многие компании просто не хотят раскрывать как они сделали ту или иную фичу. Опять же - зачем?Конкурентов плодить? ;)

    В то же время, большие опен-сорс решения все же имеют место быть (но у них изначально опен-сорс как фича, или компания хочет таким образом привлечь к себе внимание. Либо компания может себе это позволить). Обычно, они сразу и всем известны, и гугляться на раз-два-три, типа react open source projects, angular open source projects и тд.
    Ответ написан
    Комментировать
  • Зачем нужен redux-thunk?

    maxfarseer
    @maxfarseer
    https://maxpfrontend.ru, обучаю реакту и компании
    Если я правильно понял вашего коллегу, то речь была не о том, что нужно асинхронные функции через setTimeout вызывать, а это был просто пример, как сделать какой-то кусочек "типа асинхронным".
    Его довод был в том, что вместо вызова dispatch из замыкания (полученного с помощью redux-thunk, например) он вызывал store.dispatch напрямую (то есть у объекта store, и этот store импортировал бы в каждом файле).

    В таком случае, у redux-thunk - одно преимущество явное - не нужно импортировать store в каждом файле.

    В остальном, все очень четко расписано в ответе Дэна Абрамова, который привел holymotion.
    Если быть кратким, то вам нужна функция dispatch, ведь именно через нее вы "диспатчите" свои экшены. Вы не можете в асинхронном ответе написать:
    ...
    axios.get('/user')
          .then(res => {
            // успешно получили данные
            dispatch({ // <-- здесь вы вызываете функцию dispatch, а если она к вам не пришла в анонимной функции, с помощью redux-thunk, то октуда вы ее возьмете?
              type: GET_PROFILE_SECCUESS
              payload: res.data
            })
          })
    ...


    Поэтому вы были бы обязаны в каждый action creator, который является асинхронным, передавать бы помимо нужных вам аргументов, еще и функцию dispatch из своего контейнера. Что не удобно. (это все есть по ссылке на stackoverflow, но более подробно)
    Ответ написан
    1 комментарий