Redux: RFC: Стартовый комплект Redux

Созданный на 1 мар. 2018  ·  56Комментарии  ·  Источник: reduxjs/redux

Основываясь на комментариях в # 2858 и ранее в # 2295, это звучит как предварительно настроенный стартовый набор из ядра Redux + некоторое общее промежуточное ПО + средства улучшения хранилища + другие инструменты могут быть полезны для начала работы с библиотекой.

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

Одновременно я хотел бы исследовать одну вещь: разделение combineReducers на собственный пакет. Это единственное, что дает предписания о том, как структурировать и управлять магазином. Очевидно, что это не единственный способ, но я беспокоюсь, что многие люди не видят этого дальше.

Что касается того, что входит в стартовый пакет, то краткий список, на мой взгляд, включает одну из шаблонных библиотек сокращения (или что-то, что мы создаем), популярное промежуточное программное обеспечение, такое как thunks и sagas, и полезные инструменты для разработчиков. У нас может быть подмножество пакетов для пользователей, специфичных для React. Фактически, я начал опрос в

Я не думаю, что нам нужно создавать опыт, подобный Create React App, с помощью инструмента командной строки и всего прочего. Но что-то из коробки, что дает отличный опыт разработки с лучшей отладкой и меньшим количеством кода.

discussion ecosystem feedback wanted

Самый полезный комментарий

Итак, э ... Я пошел и сделал кое-что:

Вещи, которые отличаются от фрагмента ранее:

  • Я добавил вариант конфигурации enhancers только потому, что
  • Я добавил зависимость selectorator и экспортировал createSelector

Мысли?

Все 56 Комментарий

ДА ДА ДА! МНЕНИЯ И ПОЖЕЛАНИЯ НА ЭТО ЕСТЬ МНОГО МНЕНИЙ! Но я сдержу себя и сначала позволю дискуссии развернуться.

Один элемент списка желаний, который я не уверен, осуществим, - это встроенный HMR для редукторов, автоматически добавляемых в функцию createReduxStore() . К сожалению, мои знания Webpack и некоторые эксперименты говорят о том, что это не очень осуществимо, потому что вам необходимо иметь жестко запрограммированные пути к файлам редуктора в обратных вызовах Webpack module.hot.accept() . Не знаю, как Parcel или другие упаковщики справляются с этим.

Итак, первоначальный запрос на обратную связь от всех:

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

Назовем 3 ключевые точки, где возможные варианты будут _изолированы_ друг от друга.

  1. Первая точка. Менеджеры редукторов
    1.0 Ваниль (здесь ли дело?)
    1.1 Immer.js
    1.2 Coredux
    1.3 100500 больше пакетов

  2. Второй момент. Промежуточное ПО
    2.0 Ваниль (это так?)
    2.1 Саги
    2.2 Эпосы
    2.3 еще 100500 пакетов.

  3. Третий момент. Реагировать на интеграцию
    3.0. Ваниль (это здесь дело?)
    3.1. Подпространство
    3.2 Переформулируйте
    3.3 еще 100500 пакетов.

4-й, бонус, балл
4.0. Тестирование всего этого на _boilerplate_.

Невозможно выбрать «избранных», например, я люблю и использую и саги, и эпосы, но можно предоставить некоторые «рецепты приготовления» и рекомендации по сочетаниям .

Например, большинство пользователей redux знают __only__ о промежуточном программном обеспечении. Небольшая часть также что-то делает с редукторами (хорошо, много _ слышали_ о immutable.js), всего несколько улучшают интеграцию с React.

Starter Kit может просто помочь построить полный и _ богатый_ подход с самого начала. Или нужно еще один стартовый комплект.

Запрошены отзывы о проблемных точках установки / шаблонных в Twitter: https://twitter.com/acemarke/status/969040835508604929

Копирую мой ответ в твиттере:

Я явно воздержался от добавления шаблона redux, поскольку IMO добавляет сложности при представлении «вашего способа» выполнения redux другому человеку. Мне бы хотелось, чтобы в коде было больше предписывающих соглашений, чтобы сделать redux более переносимым навыком.

С этой целью наличие репозитория в стиле create-redux-app - хотя и разработанного скорее как библиотека, чем как фреймворк - особенно одно, явно одобренное разработчиками Redux лучших и рекомендуемых практик, я думаю, будет иметь большое значение для укрепления и добавления ясности. о правильном использовании Redux.

Мы немного говорили об этом на Reactiflux, хотели скопировать консолидацию желаний для включения в эту ветку, некоторые из этого частично совпадают с пунктами, которые вы уже указали на @timdorr (так что это восторженное подтверждение).

  1. оболочка для createStore с лучшими настройками по умолчанию, т.е. более простой способ добавления промежуточного программного обеспечения, инструменты redux dev
  2. встроенный неизменный помощник (погружение?)
  3. Встроенный createReducer (стандартная утилита "поисковая таблица редуктора")
  4. повторно выбрать встроенный
  5. создатель действий, который придерживается FSA
  6. поддержка асинхронных действий / поддержка побочных эффектов (поток, сага, что?)

Почему бы официально не поддержать то, что уже существует, например, redux-bundler Хенрика Йоретега?

https://github.com/HenrikJoreteg/redux-bundler

Он лаконичный, самоуверенный (в хорошем смысле), позволяет повторно использовать функции, связанные с сокращением, в приложениях и по-прежнему дает хорошее решение для асинхронной обработки.

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

Вот чего я действительно хочу добиться:

  • Настройка Redux-хранилища с парой строк кода и минимальным набором настроек (используется Redux-эквивалент лозунга "zero-config JS" Webpack и Parcel).
  • Подобно CRA, конфигурация в основном скрыта, с хорошими настройками по умолчанию из коробки.
  • Включение тщательно отобранных пакетов для улучшения опыта разработчиков и, да, "уменьшения количества шаблонов". Например, Immer был бы отличным выбором, потому что он резко упрощает написание неизменной логики редуктора _и_ замораживает ваше состояние в dev. (Единственное, что я сомневаюсь, так это то, что появление «мутирующего» кода могло бы сбить с толку.)

Я хочу, чтобы эти усилия были достаточно жесткими. Я болтал с @hswolff и @nickmccurdy в Reactiflux последние пару часов, и, хотя обсуждение было отличным, мы уже рассмотрели дюжину пересекающихся вариантов использования и идей, которые могут действительно сильно усложнить ситуацию.

Я хочу собрать что-нибудь полезное, ценное и жизнеспособное без излишнего увольнения, а затем оставить другие обсуждения в стороне (например, API для создания «пакетов» или «модулей» Redux и т. Д.).

Чтобы приступить к первоначальному составлению шаблонов API, вот основная идея для 1-3 из моего списка, который я опубликовал выше:

// #1
export function createStore({
    // If an object is given it's passed to combineReducers
    // otherwise it's just used directly.
    reducer: Object<String, Function> | Function,
    // Middleware is built-in and accepts an array of middleware functions.
    middleware: Array<MiddlewareFunction>,
    // Built-in support for devtools.
    // Defaults to NODE_ENV !== production
    devTools: boolean,
    // Same as current createStore.
    preloadedState,
    // Same as current createStore.
    enhancer,
}) {};

// Re-exported for easy usage.
export function combineReducers() {}

// #2
// Re-export immer as the built-in immutability helper.
import immer from 'immer';
export const createNextState = immer;

// #3
// Export an already written version of createReducer .
// Same thing as https://redux.js.org/recipes/structuring-reducers/refactoring-reducers-example#reducing-boilerplate
export function createReducer() {}

Да, я это понимаю. Тогда я бы ожидал, что он либо всегда будет добавлять thunk() в начало списка промежуточного программного обеспечения, либо, возможно, только в том случае, если вы сами не поставили промежуточное программное обеспечение. Возможно, мы даже не захотим позволять пользователю указывать здесь усилители. Мы добавили бы applyMiddleware() автоматически, если есть промежуточное ПО, и использовали бы функцию composeWithDevtools из redux-devtools-extension если devTools : true . Я думаю, что для целей этой «простой настройки» мы можем захотеть исключить «усилители» из того, что пользователь может настраивать.

+1 к устранению энхансеров.

Если ваш преобразователь автоматически добавляется, мы должны иметь возможность получить свой торт и съесть его, экспортировав функцию, которую мы будем использовать для добавления промежуточного программного обеспечения по умолчанию:

export function createDefaultMiddleware(...additional) {
    return [thunk(), ...additional],
}

// Within a user's application
createStore({
    // By default it's just createDefaultMiddleware()
    // However if you want to add any other middleware you can.
    middleware: createDefaultMiddleware(any, other, middleware)
})

Да, примерно об этом я и думал. Моя главная забота - выяснить, не пытается ли пользователь случайно предоставить свой собственный экземпляр thunk .

Я решил немного поиграть сегодня вечером. Вот первый вариант. Мысли?

// configureStore.js
import {createStore, compose, applyMiddleware, combineReducers} from "redux";
import { composeWithDevTools } from 'redux-devtools-extension';
import createNextState from "immer";

import isPlainObject from "./isPlainObject";

import thunk from "redux-thunk";


const IS_DEVELOPMENT = process.env.NODE_ENV !== "production";

export function createDefaultMiddleware(...additional) {
    return [thunk, ...additional];
}

export function configureStore(options = {}) {
    const {
        reducer,
        middleware = createDefaultMiddleware(),
        devTools = IS_DEVELOPMENT,
        preloadedState,
    } = options;

    let rootReducer;

    if(typeof reducer === "function") {
        rootReducer = reducer;
    }
    else if(isPlainObject(reducer)) {
        rootReducer = combineReducers(reducer);
    }
    else {
        throw new Error("Reducer argument must be a function or an object of functions that can be passed to combineReducers");
    }

    const middlewareEnhancer = applyMiddleware(...middleware);

    const storeEnhancers = [middlewareEnhancer];

    let finalCompose = devTools ? composeWithDevTools : compose;

    const composedEnhancer = finalCompose(...storeEnhancers);

    const store = createStore(
        rootReducer,
        preloadedState,
        composedEnhancer
    );

    return store;
}

export function createReducer(initialState, actionsMap) {
    return function(state = initialState, action) {
        const {type, payload} = action;

        return createNextState(state, draft => {
            const caseReducer = actionsMap[type];

            if(caseReducer) {
                return caseReducer(draft, payload);
            }

            return draft;
        });
    }
}
export {createNextState, combineReducers};

И обязательный пример todo app:

import {configureStore, createReducer} from "./configureStore";

const ADD_TODO = "ADD_TODO";
const TOGGLE_TODO = "TOGGLE_TODO";
const SET_VISIBILITY_FILTER = "SET_VISIBILITY_FILTER";

function setVisibility(state, newFilterType) {
    return newFilterType;
}

const visibilityReducer = createReducer("SHOW_ALL", {
    [SET_VISIBILITY_FILTER] : setVisibility
});


function addTodo(state, newTodo) {
    state.push({...newTodo, completed : false});
}

function toggleTodo(state, payload) {
    const {index} = payload;

    const todo = state[index];
    todo.completed = !todo.completed;
}

const todosReducer = createReducer([], {
    [ADD_TODO] : addTodo,
    [TOGGLE_TODO] : toggleTodo
});


const preloadedState = {
    todos: [{
        text: 'Eat food',
        completed: true
    }, {
        text: 'Exercise',
        completed: false
    }],
    visibilityFilter : 'SHOW_COMPLETED'
};


const store = configureStore({
    reducer : {
        todos : todosReducer,
        visibilityFilter : visibilityReducer,
    },
    preloadedState,
});

const exercise1 = store.getState().todos[1];

store.dispatch({type : "TOGGLE_TODO", payload : {index : 1}});

const exercise2 = store.getState().todos[1];

console.log("Same object: ", exercise1 === exercise2);

store.dispatch({type : "SET_VISIBILITY_FILTER", payload : "SHOW_COMPLETED"});

console.log(store.getState());

Я думаю, что это хорошее начало и отличное начало для библиотеки, обсуждаемой в этой ветке. Он охватывает пункты 1, 2 , 3 и 6 из моего списка желаемых функций выше.

Было бы здорово поработать над этим, но это прочная основа.

Вместо того, чтобы сосредоточиться на реализации, я бы хотел, чтобы мы сосредоточились на DX. Что такое экспорт / API и как они используются? Я думаю, что это отличный шанс пройти только настройку, а также посмотреть, как люди используют магазин. Несколько случайных идей:

Более простые пары редуктор / действие:

Упростите объединение ваших редукторов и действий вместе с их выводом состояния. Это грубо, но вот основная идея:

import { createStore, createActionPack, combineActionPacks } from 'redux/starter'

const counter = createActionPack({
  increment: counter => counter + 1,
  decrement: counter => counter - 1,
  set: (_, value) => value
}, 0)

const posts = createActionPack({
  load: async () => await fetch('/posts'),
  create: async (state, text) => state.push(await fetch('/posts/new', { body: { text } }))
}, [])

const store = createStore(
  combineActionPacks(
    counter,
    posts
  )
)

store.dispatch(counter.increment())
store.dispatch(counter.set(42))

await store.dispatch(posts.load())
await store.dispatch(posts.create('First!'))

Магазин Синглтон

Этот меня никоим образом не поддерживает, но я вспоминал те времена, когда у нас были синглтоны истории в React Router. Это было не идеально, но имело некоторую ценность.

import { store, configureStore } from 'redux/starter'

configureStore(reducer, middleware, initialState)

store.dispatch(someAction())
store.getState()

Возможность настройки через import

Я оставлю свои дурацкие напоследок. Но что, если мы разрешили настройку путем импорта файлов. Нам понадобится некоторая скрытая глобальная передача, которая становится беспорядочной / хлопотной. Но, опять же, основное внимание уделяется пользователю, а не нашей стороне.

import { createStore } from 'redux/starter'
import 'redux/starter/devtools'
import 'redux/starter/logger'
import 'redux/starter/immutable'

// OR!

import { createStore } from 'redux/starter/developer'
import { createStore } from 'redux/starter/production'

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

Ладно, пока что это от меня. Опять же, я хочу думать прежде всего о пользователях. Какие бы грязные и уродливые хаки мы ни использовали, чтобы реализовать это, не имеют значения. Все дело в отличном DX с меньшим количеством написанного кода и меньшей необходимой конфигурацией.

Мне нравятся эти идеи до сих пор. Моим единственным желанием, каким бы это ни оказалось, был изящный доступ к нижнему уровню, стандартному Redux api. У людей должен быть естественный путь для настройки или извлечения. Будь то несколько дней, год или два, все должно быть просто. Блокировка - одна из проблем, с которыми я сталкиваюсь (из моей собственной попытки сделать это с помощью Jumpstate и из более поздних библиотек, таких как Rematch). Чем больше мы сможем этого избежать, тем вкуснее будет во рту у людей :)

Да, я видел довольно много утилит, которые делают что-то вроде этого "пакета действий" (по крайней мере, в том, что касается аспекта "напишите несколько редукторов, превратите ключи в типы действий и создатели действий"), и я подумывал о том, чтобы бросить это как дополнительный элемент - просто еще не дошел. Не уверен насчет аспекта "combActionPack".

Прошлой ночью @hswolff . Я хотел бы рассмотреть возможность добавления / реэкспорта библиотеки selectorator , которая, похоже, является надмножеством Reselect API с некоторыми дополнительными полезными преимуществами:

import createSelector from 'selectorator';

// selector created with single method call
const getBarBaz = createSelector(['foo.bar', 'baz'], (bar, baz) => {
  return `${bar} ${baz}`;
});

Это помогло бы сократить количество рукописных селекторов «простого ввода», таких как const selectTodos = state => state.todos .

Я не уверен, что вижу пользу от добавления библиотеки селекторов. Мы также должны высказать свое мнение о форме государства, которая благодаря этому возможна.

По крайней мере частично, потому что пользователю нужно установить на один элемент меньше в package.json .

Я думаю, что библиотека селекторов была бы потрясающей.

Также актуально: недавняя статья о стартовом наборе apollo-boost

Если мы сможем расширить API connect react-redux для использования повторного выбора (или подобной библиотеки селекторов), когда mapStateToProps является Array , мы могли бы поощрять использование селекторов и делать их очень удобными, не нарушая совместимости. Я не думаю, что эта библиотека должна быть обязательно связана с React или react-redux , но, возможно, мы могли бы справиться с этой расширяемостью с помощью опции для react-redux или предоставить другой пакет, обертывающий стартовый комплект с react-redux поддержка.

Да, я не собираюсь ничего делать с React-Redux для этого начального MVP.

В таком случае, есть ли хороший способ добавить абстракцию для селекторов на уровне Redux, или это то, что мы могли бы эффективно сделать только поверх react-redux? Проблема в том, что мы не хотели бы, чтобы это было несовместимо с react-redux, поэтому я думаю, если это невозможно, мы должны пока отказаться от селекторов.

Пока он реализует API магазина, он совместим с react-redux. Мы не стремимся ломать этот API, просто улучшаем DX.

В этом есть смысл. Я не использовал селекторы вне react-redux, поэтому мне было интересно, применимы ли они для настройки самого Redux здесь.

@timdorr +1 по желанию, выраженному с помощью более простых пар редуктор / действие. Я также хотел бы представить способ упростить создание модуля redux (также известного как шаблон уток), чтобы создание редуктора, создателей действий и селекторов было гораздо более приятным и простым в использовании опытом.

Я действительно думаю, что для того, чтобы найти решение этой проблемы, которое делает большинство людей счастливыми, потребуется немного больше сброса велосипедов, и мне интересно, можем ли мы добавить это в следующую версию, чтобы она не блокировала начальную выпускать.

Я думаю, что то, что @markerikson создал в своем комментарии, уже значительно сокращает количество шаблонов и может стать отличным начальным предварительным релизом.

После этого мы можем заняться другими громоздкими аспектами Redux (сокращение / действие / создание селектора).

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

Если вы думаете, что он достаточно готов, я думаю, было бы неплохо запустить репозиторий, чтобы мы могли протестировать эту настройку с помощью примера кода и немного поработать (или, может быть, пакет в функциональной ветви монорепозитория, и мы могли бы сотрудничать через PR).

Конечно. Я посмотрю, смогу ли я что-нибудь настроить сегодня немного позже.

Нам не нужен другой репозиторий. Это будет существовать в текущем. Пожалуйста, сделайте что-нибудь для пиара.

Должен ли он быть частью основного пакета redux как отдельный импорт (чтобы он был полностью обратно совместим) или вы бы предпочли монорепозиторий с несколькими пакетами? Я думаю, что первого будет достаточно, мы всегда можем использовать другой экспорт файла, не создавая новый пакет, если он станет слишком большим.

Я бы хотел поиграть с этим как с отдельным репо / пакетом для начала, правда.

Возможно, будет проще использовать существующую настройку инструментов в этом репо, поскольку ее объединение в будущем может быть подвержено ошибкам. Нам также, вероятно, не нужна поддержка другого синтаксиса, потому что мы не делаем этот React специфичным.

Если это будет один файл с некоторой предварительной конфигурацией, то проще всего сохранить его здесь. Из-за зависимостей это должен быть отдельный пакет. Мы не хотим обременять ими существующие приложения.

Опять же, я не думаю, что нам нужно переходить на монорепозиторий, но у нас может быть папка для конкретных упакованных сборок, если мы начнем создавать более одной. Просто папка starter на данный момент с собственным package.json должна помочь.

Мне нравится идея сохранить его локально для основного пакета redux, если он использует только локальный код для самого сокращения. Я сомневаюсь, если мы начнем привлекать внешние зависимости, чтобы поддержать идеи, выраженные здесь.

Я думаю, что некоторые внешние зависимости, такие как immer, thunk / обещание / сага и повторный выбор, будут неоценимы для наших целей здесь и стоят дополнительных зависимостей для стартера, хотя мы, возможно, не хотим, чтобы эти зависимости от самого основного пакета redux .

Итак, э ... Я пошел и сделал кое-что:

Вещи, которые отличаются от фрагмента ранее:

  • Я добавил вариант конфигурации enhancers только потому, что
  • Я добавил зависимость selectorator и экспортировал createSelector

Мысли?

Как человек, который только что научился Redux (и React) за последние пару недель, мне не терпится увидеть финальный продукт. Я уверен, что мне нужно будет почистить массу вещей в моем коде.

😏 👍

Итак, поскольку долгая идея состоит в том, чтобы упростить использование redux, я мог бы предложить 2 момента:

  1. Добавьте встроенную функцию буквально в expect(mapStateToProps(state)).toEqual(mapStateToProps(state)) . Просто чтобы побудить людей создавать лучший код. Я никогда не видел подобных тестов, но _not-very-pure_ mapStateToProps - одна из проблем с редукцией.

  2. Считайте принятие чем-то вроде memoize-state . Это похоже на Immer.js для селекторов. Ключевой момент - клиент мог просто написать mapStateToProps или selector в той форме, которую он предпочитает, и запоминать ее. Это даже может решить эту проблему повторного выбора с помощью «Совместного использования селекторов с реквизитами для нескольких экземпляров компонентов» без потери «общей» мемоизации между экземплярами. Просто запомните материал

  1. Я понимаю, что вы имеете в виду, говоря о том, что рекомендуете чистые селекторы, но нечистый идемпотентный селектор все же может пройти этот тест. Мне больше нравится второе предложение.
  2. Звучит круто, поэтому мы бы просто обернули селекторы так же, как и редукторы для погружения, верно?

Тем не менее, как мы обсуждали выше, это больше похоже на реакцию-редукцию, чем на то, что было бы в стартовом пакете, который не зависит от React.

Это действительно круто!

Однако у меня есть одна просьба / небольшая обратная связь; Я бы предпочел, чтобы Immer не использовался неявно.

Погружение отличное . Это стало одной из моих любимых утилит. Но даже при его явном использовании ( produce(baseState, draftState => ... ) я беспокоюсь о том, что другие люди, которые не знакомы с ним, просматривают мой код и не понимают, что я могу делать эти изменчивые вещи только из-за суперспособностей Immer.

Теперь, как API выглядит, я могу представить новичков, не осознающих, что состояние редукции должно быть неизменным. Я думаю, что это недоразумение сильно укусит их, когда они попытаются использовать Redux без этого стартового набора.

Я вижу, что createNextState уже является экспортом, так почему бы не побудить пользователей использовать его явно:

import {createReducer, createNextState} from "@acemarke/redux-starter-kit";

function addTodo(state, newTodo) {
    return createNextState(state, draftState => {
        draftState.push({...newTodo, completed : false});
    });
}

(извиняюсь, если я неправильно понял, как createNextState предназначен для использования! Я вообще не копался в этом)

См. Https://github.com/markerikson/redux-starter-kit/issues/5.

Теперь, как API выглядит, я могу представить новичков, не осознающих, что состояние редукции должно быть неизменным. Я думаю, что это недоразумение сильно укусит их, когда они попытаются использовать Redux без этого стартового набора.

На мой взгляд, мы должны рекомендовать не использовать Redux напрямую в пользу этого пакета, когда он будет завершен, из-за https://github.com/reactjs/redux/issues/2858. По сути, мы хотим либо предупредить, либо защитить пользователей от всех мутаций по умолчанию, но мы не можем легко сделать это в ядре, не нарушая работу, поэтому мы должны рекомендовать не использовать ядро, за исключением крайних случаев, когда начального набора недостаточно. Это похоже на то, как React рекомендует CRA, а Redux рекомендует react-redux при использовании React.

Я вижу, что createNextState уже является экспортом, так почему бы не побудить пользователей использовать его явно:

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

Я вижу, как много людей рекомендуют использовать libs например immer.js , что, по моему скромному мнению, заключается в невольном отклонении мотивации обучения и соблюдении требований store .

Все мы знаем, что хранилище не может быть изменено, поэтому я бы предпочел иметь механизм проверки, в котором он проверяет экземпляр newState на ( === ) previousState и если это тот же экземпляр, выдает ошибку.

Таким образом, все будут вынуждены изучить правила и требования store .

PS: Я действительно понимаю преимущество immer и я абсолютно ничего не имею против этого, но мы приближаемся к тому моменту, когда люди, наконец, понимают концепцию, это вызовет огромный источник путаницы, и технически говоря: если мы проведем тест, мы ничего не будем делать, кроме как добавить дополнительный уровень сложности, чтобы ослабить библиотеку.

Личные предложения:

logger , devTools и Thunk должны быть добавлены по умолчанию к Starter , остальное, я считаю, является более личным выбором.

Все мы знаем, что хранилище не может быть изменено, поэтому я бы предпочел иметь механизм проверки, в котором он проверяет экземпляр newState на (===) previousState, и если это тот же экземпляр, выдает ошибку.

Бывают случаи, когда в зависимости от действия вы не хотите, чтобы состояние изменялось, поэтому вы должны вернуть тот же экземпляр хранилища, чтобы сэкономить память и предотвратить любые ложноположительные различия. Даже если мы обошли эту проблему, похоже, что Redux не нуждается в валидаторе в ядре, и я думаю, что Immer является хорошей защитой для этого лично. Я согласен с тем, что это в некоторой степени противоречит цели изучения Redux, но я вижу, что так много разработчиков, изучающих Redux, не хотят изучать чистый FP или не знают об этом.

если мы протестируем его, мы ничего не будем делать, кроме как добавить дополнительный уровень сложности, чтобы ослабить библиотеку.

Насколько мне известно, способ реализации Immer Proxy имеет накладные расходы на производительность только в том случае, если он действительно видоизменен, поэтому типичные неизменяемые редукторы обновлений не должны иметь накладных расходов на производительность. Думаю, это нормальный баланс.

Регистратор, devTools и Thunk должны быть добавлены по умолчанию в Starter, остальное, я считаю, является более личным выбором.

Есть и другие вещи, которые я хотел бы удалить (хотя я лично не вижу огромного преимущества регистратора перед инструментами разработчика, которое компенсирует его накладные расходы на производительность), см. Https://github.com/markerikson/ redux-starter-kit / вопросы / 19. Однако я не против добавления дополнительных вещей, если они обратно совместимы, как наше текущее использование Immer и Thunk.

Бывают случаи, когда в зависимости от действия вы не хотите, чтобы состояние изменялось, поэтому вы должны вернуть тот же экземпляр хранилища, чтобы сэкономить память и предотвратить любые ложноположительные различия. Даже если мы обошли эту проблему, похоже, что Redux не нуждается в валидаторе в ядре, и я думаю, что Immer является хорошей защитой для этого лично. Я согласен с тем, что это в некоторой степени противоречит цели изучения Redux, но я вижу, что так много разработчиков, изучающих Redux, не хотят изучать чистый FP или не знают об этом.

@nickmccurdy Я полностью понимаю вашу точку зрения, и я согласен с тем, что у нас не должно быть препятствий для обучения из-за некоторых концепций FP, мутации и т.д ... Но как педагог я твердо верю в то, что не следует приукрашивать ученика скрывая от них сложность. В любом случае, это просто вопрос вкуса, я профессионал в обучении и прогрессе, и, глядя на это предложение, мои инстинкты каким-то образом подсказывают мне, что мы будем двигаться вперед с принятием, но возвращаясь к стандартам. Просто обратите внимание: подумайте обо всем контенте в сети, который преподает стандарты Redux прямо сейчас, и о том, как он, наконец, набирает обороты.

Насколько мне известно, способ реализации Immer Proxy имеет накладные расходы на производительность только в том случае, если он действительно видоизменен, поэтому типичные неизменяемые редукторы обновлений не должны иметь накладных расходов на производительность. Думаю, это нормальный баланс.

Когда я имею в виду добавление уровня сложности, я имею в виду, что Immer никогда не было, и теперь это может быть, нам нужно будет поддерживать его в библиотеке, тестировать, оценивать проблемы с производительностью и, наконец, что не менее важно этот раздел здесь вызывает у меня опасения:

Immer.js - Автоматическое замораживание
Immer автоматически замораживает любые деревья состояний, которые были изменены с помощью команды product. Это защищает от случайных изменений дерева состояний вне производителя. Это влияет на производительность, поэтому рекомендуется отключить этот параметр в рабочей среде. По умолчанию он включен. По умолчанию он включен во время локальной разработки и отключен в производственной среде. Используйте setAutoFreeze (true / false), чтобы явно включить или выключить эту функцию.

И внезапно теперь нам также нужно поддерживать функции, добавленные в Development / Prod . Это просто хороший объем работы и беспокойство из-за небольшого обмена, но, опять же, это только мое личное мнение.

@codedavinci : цель этой redux-starter-kit библиотеки - добавить полезные инструменты и абстракцию поверх «базового» процесса установки хранилища Redux. Также обратите внимание, что это _не_ не входит в само ядро ​​Redux, а скорее в отдельную библиотеку, которую мы хотели бы в конечном итоге сделать "официальной" частью организации Redux.

Весь ваш существующий код Redux будет работать. Все существующие учебники по-прежнему будут в порядке. Мы просто пытаемся добавить официально поддерживаемый более простой подход к настройке и использованию Redux.

@markerikson Я понимаю цель иметь стартовый комплект, и я полностью Immer.js которая меняет концепцию библиотеки, люди в конечном итоге узнают starter-kit и полностью игнорируют основные концепции. Девиз: «Никакой магазинной мутации», Redux всегда продавал его, это часть бренда.

PS: Я полностью понимаю, что Immer.js ничего не мутирует, а скорее помогает вам этого не делать, я просто говорю о разрешенных синтаксических стандартах, таких как push , splice ...

Может, просто я сопротивляюсь изменениям :)

@codedavinci : да, я понимаю суть проблемы. Тем не менее, одна из распространенных жалоб на Redux - это боль при написании правильного неизменяемого кода обновления, а Immer - просто лучшая библиотека, которую я видел для упрощения этих обновлений.

@markerikson , я немного immer и заметил, что он очень легкий, простой и эффективный. Я действительно продан :).

Какое репо вы готовите? те:

https://github.com/markerikson/redux-starter-kit
https://www.npmjs.com/package/@acemarke/redux -starter-kit
https://unpkg.com/@acemarke/redux [email protected]/

Ага, вот и все.

У @nickmccurdy есть куча PR, ожидающих обсуждения и слияния, в основном вокруг инструментов, но также есть некоторые дискуссии о том, как мы хотим сфокусировать проект в долгосрочной перспективе. Мне нужно найти время, чтобы посмотреть на них, но последние пару недель я был занят другим делом (включая доклад на конференции, который я даю завтра).

Большой прогресс @nickmccurdy & @markerikson 👍 Мне нравится его простота и эффективность. @nickmccurdy заметил, что вы очень активны в проекте, я хотел бы поговорить с вами о некоторых идеях, дайте мне знать, если вы готовы к этому! :)

Конечно, спасибо, вероятно, лучше начать открытое обсуждение нового выпуска, но вы можете связаться со мной напрямую по адресу [email protected] или в Discord.

+1 за разделение combineReducers . Я использовал его очень долго, и потому что, если это так, я особо не задумывался о том, как работает мой магазин.

В настоящее время мне нравится настраивать свою функцию редуктора следующим образом:

function reducer(prevState, event, handledNavigation = false) {
  if (event.type === 'NAVIGATION' && !handledNavigation) {
    return reducer(onNavigate(prevState, event), event, true);
  }

  const pageReducer = pageReducers[prevState.activePage];

  const nextSessionState = sessionReducer(prevState.sessionState, event);
  const nextPageState = pageReducer(prevState.pageState, nextSessionState, event);

  return {
    activePage: prevState.activePage,
    pageState: nextPageState,
    sessionState: nextSessionState,
  };
}

На самом деле, это то, что combReducers не позволяет мне делать.

@ abradley2 : мы не планируем удалять combineReducers из ядра Redux, если вы об этом спрашиваете. Но да, мы всегда говорили, что combineReducers - это утилита для наиболее распространенного варианта использования, и что вам рекомендуется написать собственную логику редуктора для вашей собственной ситуации.

У нас есть имя пакета redux-starter-kit , и репо перемещено в организацию по адресу https://github.com/reduxjs/redux-starter-kit . Закрою эту тему. Любое дальнейшее обсуждение может произойти в этом репо.

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

Была ли эта страница полезной?
0 / 5 - 0 рейтинги