Redux: RFC:Redux 入门套件

创建于 2018-03-01  ·  56评论  ·  资料来源: reduxjs/redux

根据 #2858 和更早的 #2295 中的评论,听起来像是 Redux 核心的预配置入门套件 + 一些通用中间件 + 存储增强器 + 其他工具可能有助于开始使用该库。

我已经开始保留一个包名(不过我并没有死心塌地),我们可以开始填补那里的空白。 我想在这里维护那个包的内容,所以我们不必设置另一个 repo 或任何东西。 我们可能想调查一个 monorepo,但我认为目前没有紧迫的需求。

我想同时调查一件事:将combineReducers拆分

至于入门包中的内容,我脑海中的短名单包括样板缩减库之一(或我们构建的东西)、流行的中间件,如 thunks 和 sagas,以及有用的开发工具。 我们可以为特定于 React 的用户提供一个子集包。 事实上,我开始了一项 Twitter 民意调查,以确定这是否有必要(请

我认为我们不需要使用 CLI 工具和所有爵士乐来构建类似 Create React App 的体验。 但是开箱即用的东西可以通过更好的调试和更少的代码提供出色的开发体验。

discussion ecosystem feedback wanted

最有用的评论

所以,呃...我去做了一件事:

与之前的代码段不同的地方:

  • 我加入了一个enhancers配置选项,只是因为
  • 我添加了selectorator依赖项并导出了createSelector

想法?

所有56条评论

对对对! 我对此有很多意见和愿望! 但我会克制自己,让讨论先进行。

我不确定是否可行的一个愿望清单项目是内置 HMR,用于在createReduxStore()函数中自动添加的减速器。 不幸的是,我对 Webpack 的了解和一些实验表明这不太可行,因为您必须在 Webpack module.hot.accept()回调中具有指向 reducer 文件的硬编码路径。 不确定 Parcel 或其他打包程序如何处理。

因此,最初要求每个人提供反馈:

  • 我们希望通过该软件包满足哪些关键要求?
  • 您会建议使用哪些 _existing_ 软件包来帮助满足这些要求?
  • 我们如何才能最好地组合这些包来使最终用户的事情变得简单?

让我们说出 3 个关键点,其中可能的变体将彼此 _isolated_。

  1. 第一点。 减速机管理器
    1.0 Vanilla(这里是这样吗?)
    1.1 Immer.js
    1.2 内核
    1.3 100500多包

  2. 第二点。 中间件
    2.0 Vanilla(是这样吗?)
    2.1 传奇
    2.2 史诗
    2.3 100500 多个包。

  3. 第三点。 反应集成
    3.0. 香草(这里是这种情况?)
    3.1. 子空间
    3.2 重述
    3.3 100500 多包。

4、奖金、积分
4.0 在 _boilerplate_ 中测试所有这些东西。

不可能选择“选定的”,例如我喜欢并使用 Sagas 和 Epics,但可以提供一些“烹饪收据”和组合建议。

例如,大多数 redux 用户知道 __only__ 关于中间件。 一小部分也在用 reducers 做一些事情(很多 _heard_ 关于 immutable.js),只有少数几个增强了 React 集成。

Starter Kit 可以从一开始就帮助构建完整和 _rich_ 方法。 或者需要更多的入门套件。

在 Twitter 上询问关于设置/样板痛点的反馈: https :

复制我在推特上的回复:

我已经明确避免添加 redux 样板,因为 IMO 在向另一个人介绍“你的方式”做 redux 时会增加复杂性。 我希望通过代码强制执行更多规范性约定,以使 redux 成为更便携的技能。

为此,拥有一个create-redux-app风格的 repo——然而它更像是一个库而不是一个框架——尤其是一个由 Redux 维护者明确认可的最佳和推荐实践,我认为这将大大有助于巩固和增加清晰度正确使用 Redux。

我们已经在 Reactiflux 上讨论过这个问题,想复制包含在这个线程中的愿望的整合,其中一些与您已经在@timdorr 上列出的要点重叠(所以这是一个热情的确认)。

  1. 使用更好的默认值包装 createStore,即添加中间件、redux 开发工具的更简单方法
  2. 内置不可变助手(immer?)
  3. createReducer 内置(标准的“reducer 查找表”实用程序)
  4. 重新选择内置
  5. 遵守 FSA 的动作创建者
  6. 异步动作支持/副作用支持(flux,saga,什么?)

为什么不正式支持已经存在的东西,比如 Henrik Joreteg 的 redux-bundler?

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

它简洁、自以为是(以一种好的方式),允许跨应用程序重用与 redux 相关的功能,并且仍然为异步处理提供了一个很好的解决方案。

这是一个引人入胜的项目,我真的很想进一步调查,但它也超出了我想要完成这项任务的范围。

我真正想在这里完成的是:

  • 使用几行代码和最少的配置选择来设置 Redux 存储(Webpack 和 Parcel 一直在使用 Redux 相当于“零配置 JS”标语)。
  • 与 CRA 类似,配置内容基本上是隐藏的,开箱即用的默认设置很好
  • 包含精心挑选的软件包以改善开发体验,是的,“减少样板”。 例如,Immer 将是一个不错的选择,因为它极大地简化了编写不可变的 reducer 逻辑 _and_ 冻结你在开发中的状态。 (我唯一的犹豫是“变异”的代码的外观会令人困惑。)

我希望将这项工作的范围保持在相当严格的范围内。 在过去的几个小时里,我一直在 Reactiflux 中与@hswolff@nickmccurdy聊天,虽然讨论很棒,但我们已经经历了十几个重叠的用例和想法,这些用例和想法可能会让事情变得过于复杂。

我想在没有太多自行车棚的情况下将 _something_ 有用、有价值和可行的东西放在一起,然后进行其他讨论(例如用于制作 Redux“捆绑包”或“模块”等的 API)。

为了开始一些 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() ,并使用redux-devtools-extension if devTools : truecomposeWithDevtools函数。 出于这个“简单设置”的目的,我认为我们可能希望从用户可以配置的东西中消除“增强器”。

+1 消除增强剂。

在自动添加 thunk 时,我们应该能够通过导出我们用来添加默认中间件的函数来拥有我们的蛋糕并吃掉它:

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 应用程序:

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());

我认为这是一个坚实的开始,也是本线程中讨论的 lib 的一个很好的开始。 它涵盖了我上面

在此基础上进行迭代会很棒,但这是一个坚实的基础。

我希望我们专注于 DX,而不是专注于实现。 什么是导出/API,它们是如何使用的? 我认为这是一个很好的机会,不仅可以了解配置,还可以了解人们如何使用商店。 一些随意的想法:

更简单的 Reducer/Action 对:

将您的减速器和动作与其状态输出配对变得非常容易。 这很粗糙,但这是基本思想:

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 等最近的库)。 我们越能避免这种情况,人们口中的味道就会越好:)

是的,我已经看到很多 util libs 做类似“动作包”的事情(至少就“编写一些减速器,将键转换为动作类型和动作创建者”方面而言),我正在考虑抛出作为一个附加项目 - 只是还没有到达那里。 不确定“combineActionPack”方面。

昨晚与@hswolff进行了一些额外的讨论。 我想考虑添加/重新导出选择器库,它似乎是 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入门套件的文章

如果我们可以扩展react-reduxconnect的 API 以在mapStateToPropsArray时使用 reselect(或类似的选择器库),我们可以鼓励使用选择器,并在不破坏兼容性的情况下使其非常方便。 我不认为这个库必须与 React 或react-redux使用,但也许我们可以通过react-redux的选项来处理这种可扩展性,或者提供另一个包含react-redux的入门套件的包

是的,我不打算为这个最初的 MVP 使用 React-Redux 做任何事情。

在这种情况下,有没有一种好方法可以在 Redux 级别为选择器添加抽象,或者这是我们只能在 react-redux 之上有效地做的事情? 问题是我们不希望它与 react-redux 不兼容,所以我想如果这是不可能的,我们现在应该放弃选择器。

只要实现了store API,就兼容react-redux。 我们不打算破坏该 API,只是改进 DX。

那讲得通。 我没有在 react-redux 之外使用过选择器,所以我想知道它们是否适用于在这里配置 Redux 本身。

@timdorr +1 用更简单的减速器/动作对表达的愿望。 我还想介绍一些方法来更轻松地创建 redux 模块(又名鸭子模式),以便创建减速器、动作创建器和选择器是一种更愉快、更易于使用的体验。

我确实认为找到一个让大多数人满意的解决方案需要更多的自行车脱落,我想知道我们是否可以在后续版本中添加它以便它不会阻止初始释放。

我认为@markerikson在他的评论中创建的内容已经减少了大量的样板文件,并且会成为一个很好的初始预发布版本。

之后,我们可以解决 Redux 的其他繁琐方面(redux/action/selector 创建)。

我认为试图预先解决所有问题将妨碍取得任何形式的切实进展。

如果你认为它已经准备好了,我认为启动一个存储库是个好主意,这样我们就可以用示例代码和 dogfood 测试一下这个设置(或者可能是 monorepo 功能分支中的一个包,我们可以通过 PR 协作)。

当然。 我会看看我是否可以在今天晚些时候设置一些东西。

我们不需要另一个存储库。 这将存在于当前的中。 请先将任何内容设为 PR。

这应该是主要的redux包的一部分作为单独的导入(因此这完全向后兼容)还是您更喜欢具有多个包的 monorepo? 我认为前者就足够了,如果它变得太大,我们总是可以使用另一个文件导出而无需创建新包。

我有点想把它作为一个单独的回购/包来玩,真的。

在这个 repo 中使用现有的工具设置可能更容易,因为将来合并它可能容易出错。 我们也可能不需要不同的语法支持,因为我们没有使这个 React 特定。

如果它将是一个带有一些预配置的单个文件,那么将其保留在这里将是最简单的。 由于依赖关系,它应该是一个单独的包。 我们不想用这些来束缚现有的应用程序。

同样,我认为我们不需要去 monorepo,但是如果我们开始构建多个构建,我们可以有一个用于特定打包构建的文件夹。 现在只需一个带有自己的 package.json 的starter文件夹就可以解决问题。

如果它只使用 redux 本身的本地代码,我喜欢将它保留在主要 redux 包的本地的想法。 如果我们开始引入外部依赖来支持这里表达的想法,我会更加犹豫。

我认为一些外部依赖,如 immer、thunk/promise/saga 和 reselect 对我们这里的目标是无价的,值得为初学者提供额外的依赖,尽管我们可能不希望这些依赖依赖于主要的redux包本身.

所以,呃...我去做了一件事:

与之前的代码段不同的地方:

  • 我加入了一个enhancers配置选项,只是因为
  • 我添加了selectorator依赖项并导出了createSelector

想法?

作为在过去几周内自学 Redux(和 React)的人,我迫不及待地想看到最终产品。 我确信我的代码中会有大量的东西需要清理。

😏👍

所以,只要想法是简化 redux 的使用,我可以提出两个时刻:

  1. 将内置函数添加到字面上expect(mapStateToProps(state)).toEqual(mapStateToProps(state)) 。 只是为了鼓励人们创建更好的代码。 我从未见过这样的测试,但 _not-very-pure_ mapStateToProps 是 redux 问题之一。

  2. 考虑采用类似memoize-state 的东西。 它就像用于选择器的 Immer.js。 关键点 - 客户只需以他喜欢的形式编写 mapStateToProps 或选择器,并记住它。 它甚至可以通过“在多个组件实例中与道具共享选择器”来解决这个重新选择问题,而不会丢失实例之间的“公共”记忆。 只需双重记住这些东西

  1. 我明白你在推荐纯选择器方面的意思,但不纯的幂等选择器仍然可以通过该测试。 我更喜欢第二个建议。
  2. 这听起来很酷,所以我们只需像为 immer 包装 reducer 一样包装选择器,对吗?

尽管如此,正如我们上面所讨论的,这更像是一个 react-redux 的东西,而不是 starter 包中的东西,它与 React 无关。

这真的很酷!

不过,我有一个请求/一点反馈; 我宁愿不隐式使用 Immer。

伊默很棒。 它已成为我最喜欢的实用程序之一。 但即使明确使用它( produce(baseState, draftState => ... ),我也担心其他不熟悉它的人查看我的代码,并且没有意识到由于 Immer 超能力,我只能做这些可变的东西。

API 现在的样子,我可以想象新手没有意识到 redux 状态应该是不可变的。 我认为当他们尝试使用 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 ,我们应该建议不要直接使用 Redux,而是在它完成时支持这个包

我看到 createNextState 已经是一个导出,那么为什么不鼓励用户明确使用它:

不错的主意,但我认为我们更倾向于在这里隐式,特别是因为我们不生成源代码并且添加 immer 是向后兼容的。

我看到很多人推荐使用libs类的immer.js ,从我的拙见来看,这包括在不知不觉中偏离了学习的动机并尊重了store要求。

我们都知道 store不能被改变,因此,我更愿意有一个验证机制,它检查newState实例对 ( === ) previousState如果是同一个实例,则会抛出错误。

这样每个人都会被强制学习store的规则和要求。

PS:我真正理解immer的好处,我绝对没有反对它,但我们正在达到人们终于理解这个概念的时候,它会产生巨大的混乱,从技术上讲,如果我们对它进行基准测试,我们只会增加一层额外的复杂性来放松库。

个人建议:

loggerdevToolsThunk应该添加为Starter默认值,我认为其余的更多是个人选择。

我们都知道 store 不能改变,因此,我更希望有一个验证机制,它根据 ( === ) previousState 检查 newState 实例,如果它是同一个实例,则会抛出错误。

在某些情况下,根据您不希望状态更改的操作,您将返回相同的存储实例以节省内存并防止任何误报差异。 即使我们解决了这个问题,Redux 似乎也不希望在核心中使用验证器,我认为 Immer 是一个不错的保护措施。 我确实同意这在某种程度上违背了学习 Redux 的目的,但我看到很多学习 Redux 的开发人员不想学习纯 FP 或不了解它。

如果我们对它进行基准测试,我们只会增加一层额外的复杂性来放松库。

据我所知,Immer 实现代理的方式只有在它实际发生变异时才会有性能开销,因此典型的不可变更新减速器不应该有性能开销。 我认为这是一个不错的平衡。

记录器、devTools 和 Thunk 应该作为 Starter 的默认添加,我认为其余的更多是个人选择。

还有一些我想考虑删除的其他东西(尽管我个人认为记录器相对于弥补其性能开销的开发人员工具没有巨大的优势),请参阅https://github.com/markerikson/ redux-starter-kit/issues/19. 但是,如果它们像我们目前使用的 Immer 和 Thunk 那样重新兼容,我不反对添加更多东西。

在某些情况下,根据您不希望状态更改的操作,您将返回相同的存储实例以节省内存并防止任何误报差异。 即使我们解决了这个问题,Redux 似乎也不希望在核心中使用验证器,我认为 Immer 是一个不错的保护措施。 我确实同意这在某种程度上违背了学习 Redux 的目的,但我看到很多学习 Redux 的开发人员不想学习纯 FP 或不了解它。

@nickmccurdy我完全理解你的观点,我同意我们不应该因为 FP、Mutation 等的一些概念而阻碍学习......对他们隐藏复杂性。 无论如何,这只是一个品味问题,我是一个专业的学习和前进的人,看着这个提案,我的直觉不知何故告诉我,我们会在接受的情况下前进,但会随着标准而退步。 请注意,想想现在网络上所有关于 Redux 标准的内容,以及它是如何最终流行起来的。

据我所知,Immer 实现代理的方式只有在它实际发生变异时才会有性能开销,因此典型的不可变更新减速器不应该有性能开销。 我认为这是一个不错的平衡。

当我的意思是增加一层复杂性时,我的意思是Immer从来没有存在过,现在可能存在,我们必须在库中支持它,测试,评估性能问题,最后但并非最不重要此处的这一部分让我感到担忧:

Immer.js - 自动冻结
Immer 会自动冻结任何使用生产修改的状态树。 这可以防止在生产者之外意外修改状态树。 这会影响性能,因此建议在生产中禁用此选项。 默认情况下它是启用的。 默认情况下,它在本地开发期间打开,并在生产中关闭。 使用 setAutoFreeze(true / false) 显式打开或关闭此功能。

突然之间,我们还需要支持在Development / Prod添加的功能。 这只是大量的工作,令人担忧的是没有多少可以权衡,但同样,这只是我的个人意见。

@codedavinci :这个redux-starter-kit库的重点是在“基本”Redux 商店设置过程之上添加有用的工具和抽象。 另外,请注意,这_不是_进入 Redux 核心本身,而是进入一个单独的库,我们希望最终将其作为 Redux 组织的“官方”部分。

您现有的所有 Redux 代码都可以使用。 所有现有的教程仍然可以。 我们只是尝试添加一种官方支持的更简单的方法来设置和使用 Redux。

@markerikson我理解拥有入门工具包的目标,我对上述所有内容完全失望,只是有点抗拒拥有像Immer.js这样的库会改变库的概念,人们最终会学习starter-kit模式并完全忽略核心概念。 没有商店突变是座右铭,Redux 一直在销售它,它是品牌的一部分。

PS:我完全理解Immer.js不会改变任何东西,而是帮助你不要改变,我只是在谈论允许的语法标准,例如pushsplice ...

也许,这只是我自己抵制变化:)

@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,
  };
}

这是 combineReducers 并没有真正让我做的事情。

@abradley2 :我们不打算从 Redux 核心中删除combineReducers ,如果这是您的要求的话。 但是,是的,我们一直说combineReducers是最常见用例的实用程序,我们鼓励您根据自己的情况编写自定义的 reducer 逻辑。

我们已经获得了redux-starter-kit包名称,并且 repo 已移至https://github.com/reduxjs/redux-starter-kit的组织中。 要关闭这个线程。 任何进一步的讨论都可以在该 repo 中进行。

此外,我开始在默认情况下添加变异和可序列化检查。

此页面是否有帮助?
0 / 5 - 0 等级

相关问题

captbaritone picture captbaritone  ·  3评论

CellOcean picture CellOcean  ·  3评论

parallelthought picture parallelthought  ·  3评论

ramakay picture ramakay  ·  3评论

dmitry-zaets picture dmitry-zaets  ·  3评论