Redux: RFC: Redux Starter Kit

تم إنشاؤها على ١ مارس ٢٠١٨  ·  56تعليقات  ·  مصدر: reduxjs/redux

استنادًا إلى التعليقات الواردة في # 2858 وما قبله في # 2295 ، يبدو الأمر وكأنه مجموعة بداية مكونة مسبقًا من Redux core + بعض البرامج الوسيطة الشائعة + معززات المتجر + أدوات أخرى قد تكون مفيدة لبدء استخدام المكتبة.

لقد بدأت بحجز اسم الحزمة (لكنني لست مضبوطًا على ذلك) ويمكننا البدء في ملء الفراغات هناك. أرغب في الاحتفاظ بمحتويات تلك الحزمة هنا ، حتى لا نضطر إلى إعداد ريبو آخر أو أي شيء آخر. قد نرغب في التحقيق في monorepo ، لكن لا أعتقد أن هناك حاجة ملحة حاليًا.

هناك شيء واحد أود التحقيق فيه في نفس الوقت: تقسيم combineReducers إلى الحزمة الخاصة به. إنه الشيء الوحيد الذي يحصل على إرشادات حول كيفية هيكلة المتجر وتشغيله. من الواضح أنها ليست الطريقة الوحيدة ، لكنني أشعر بالقلق من أن الكثير من الناس لا يرون ما وراءها.

بالنسبة إلى ما يتم تضمينه في حزمة المبتدئين ، فإن القائمة المختصرة في ذهني تتضمن واحدة من مكتبات الاختزال المعيارية (أو أي شيء نقوم ببنائه) ، والبرمجيات الوسيطة الشائعة مثل thunks and sagas ، وأدوات التطوير المفيدة. يمكن أن يكون لدينا حزمة مجموعة فرعية لمستخدمي React المحددين. في الواقع ، لقد بدأت استطلاعًا على Twitter لمعرفة ما إذا كان ذلك ضروريًا (من فضلك RT!).

لا أعتقد أننا بحاجة إلى إنشاء تجربة تشبه إنشاء تطبيق React باستخدام أداة CLI وكل موسيقى الجاز هذه. ولكن هناك شيء خارج الصندوق يوفر تجربة مطور رائعة مع تصحيح أخطاء أفضل وأقل كود.

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 كريدوكس
    1.3 100500 حزم أخرى

  2. النقطة الثانية. الوسيطة
    2.0 الفانيليا (هل هذا هو الحال؟)
    2.1 الملاحم
    2.2 الملاحم
    2.3 100500 حزم أخرى.

  3. النقطة الثالثة. تفاعل التكامل
    3.0 الفانيليا (هل هذا هو الحال هنا؟)
    3.1. الفضاء الجزئي
    3.2 أعد صياغة
    3.3 100500 حزم أخرى.

الرابعة ، المكافأة ، النقطة
4.0 اختبار كل هذه الأشياء في _boilerplate_.

من المستحيل اختيار "الأشخاص المختارين" ، على سبيل المثال ، أحب واستخدام كل من Sagas و Epics ، ولكن من الممكن تقديم بعض "إيصالات الطهي" والتوصيات الخاصة بالمجموعات .

على سبيل المثال ، يدرك معظم مستخدمي redux __only__ حول البرامج الوسيطة. يقوم جزء صغير أيضًا بعمل شيء ما باستخدام المخفضات (حسنًا ، سمعنا كثيرًا عن immutable.js) ، فقط عدد قليل منها يعزز تكامل React.

يمكن أن تساعد مجموعة المبتدئين في بناء نهج كامل وثري من البداية. أو يحتاج المرء إلى أكثر من مجموعة Starter Kit.

طُلب منك الحصول على تعليقات بشأن نقاط ألم الإعداد / المعيارية على Twitter: https://twitter.com/acemarke/status/969040835508604929

نسخ ردي على تويتر:

لقد ابتعدت صراحةً عن إضافة أداة معيارية redux لأن IMO تضيف تعقيدًا عند تقديم "طريقتك" في القيام بالإعادة إلى شخص آخر. أحب المزيد من الاتفاقيات الإرشادية التي يتم فرضها عبر التعليمات البرمجية لجعل الإعادة مهارة أكثر قابلية للنقل.

تحقيقًا لهذه الغاية ، فإن امتلاك نمط الريبو create-redux-app style - ولكن تم تصميمه كمكتبة أكثر من كونه إطارًا - خاصةً ما تم اعتماده بشكل صريح من قِبل المشرفين على Redux لأفضل الممارسات الموصى بها ، وأعتقد أنه سيقطع شوطًا طويلاً في ترسيخ وإضافة الوضوح على استخدام Redux الصحيح.

لقد تحدثنا قليلاً عن هذا على Reactiflux ، وأردنا نسخ دمج رغبات لإدراجها في هذا الموضوع ، وبعض هذا يتداخل مع النقاط التي أدرجتها بالفعل timdorr (لذا فهو تأكيد متحمس).

  1. التفاف حول createStore مع إعدادات افتراضية أفضل ، أي طريقة أسهل لإضافة برمجيات وسيطة ، أدوات مطور redux
  2. بنيت في مساعد ثابت (immer؟)
  3. createReducer مدمج (الأداة المساعدة القياسية "جدول بحث المخفض")
  4. إعادة تحديد المدمج
  5. منشئ الإجراء الذي يلتزم بهيئة الخدمات المالية
  6. دعم العمل غير المتزامن / دعم الآثار الجانبية (التمويه ، الملحمة ، ماذا؟)

لماذا لا ندعم رسميًا شيئًا موجودًا بالفعل ، مثل أداة إعادة التجميع الخاصة بـ Henrik Joreteg؟

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

إنها موجزة ومعقولة (بطريقة جيدة) ، وتسمح بإعادة استخدام الوظائف المرتبطة بالإعادة عبر التطبيقات ولا تزال تقدم حلاً جيدًا للتعامل غير المتزامن.

إنه مشروع رائع المظهر ، وأريد حقًا إجراء مزيد من التحقيق فيه ، ولكنه أيضًا خارج نطاق ما أريد القيام به بهذه المهمة.

ما أريد حقًا تحقيقه هنا هو:

  • إنشاء متجر Redux مع سطرين من التعليمات البرمجية والحد الأدنى من خيارات التكوين المطلوبة (تم استخدام مكافئ Redux لسطر علامة Webpack و Parcel "zero-config JS").
  • على غرار CRA ، يتم إخفاء عناصر التكوين بشكل أساسي ، مع وجود إعدادات افتراضية جيدة خارج الصندوق
  • تضمين الحزم المختارة بعناية لتحسين تجربة التطوير ، ونعم ، "تقليل النموذج المعياري". على سبيل المثال ، سيكون Immer خيارًا رائعًا لأنه يبسط بشكل كبير كتابة منطق مخفض ثابت _ ويجمد حالتك في dev. (ترددي الوحيد هناك هو أن ظهور الشفرة "المتحولة" سيكون محيرًا).

أريد أن أبقي هذا الجهد محكمًا إلى حد ما. لقد كنت أتحدث مع nickmccurdy في Reactiflux خلال الساعات القليلة الماضية ، وعلى الرغم من أن المناقشة كانت رائعة ، فقد مررنا بالفعل بالعشرات من حالات الاستخدام المتداخلة والأفكار التي يمكن أن تزيد من تعقيد الأمور.

أريد أن أحصل على _شيء ما_ مفيدًا وذا قيمة وقابلة للتطبيق معًا دون الكثير من التفرغ للدراجات ، ثم أقوم بإجراء مناقشات أخرى جانبًا (مثل واجهة برمجة تطبيقات لإنشاء "حزم" أو "وحدات نمطية" من Redux ، إلخ).

لبدء بعض التنسيقات الأولية لواجهات برمجة التطبيقات ، إليك فكرة أساسية لـ 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 على القضاء على معززات.

عند إضافة نقطة 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 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. ما هي الصادرات / واجهات برمجة التطبيقات وكيف يتم استخدامها؟ أعتقد أنها فرصة رائعة لتجاوز التكوين فقط والنظر أيضًا في كيفية استخدام الأشخاص للمتجر. بعض الأفكار العشوائية:

أزواج المخفض / الإجراء أسهل:

اجعل من السهل جدًا إقران المخفضات والإجراءات الخاصة بك جنبًا إلى جنب مع مخرجات الحالة الخاصة بهم. هذا تقريبي ، ولكن إليك الفكرة الأساسية:

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!'))

متجر Singleton

هذا لم يتم بيعي به بأي وسيلة ، لكنني كنت أفكر في الأيام التي كان لدينا فيها تاريخ فردي في 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 القياسية. يجب أن يكون هناك مسار طبيعي للناس لتخصيصه أو إخراجه. سواء كان ذلك في غضون أيام قليلة أو عام أو عامين ، يجب أن يكون الأمر بسيطًا. القفل هو إحدى المشكلات التي أراها (من محاولتي الخاصة في ذلك مع Jumpstate ومن مكتبات أحدث مثل Rematch). وكلما استطعنا تجنب ذلك ، كلما كان الذوق الرفيع في أفواههم :)

نعم ، لقد رأيت عددًا غير قليل من الأدوات التي تستخدم libs التي تقوم بأشياء مثل "حزمة الإجراءات" (على الأقل بقدر ما يتعلق الأمر "بكتابة بعض المخفضات ، وتحويل المفاتيح إلى أنواع الإجراءات ومنشئي الإجراءات") ، وكنت أفكر في طرح هذا كعنصر إضافي - لم يتم الوصول إليه بعد. لست متأكدًا من جانب "combActionPack".

أجريت بعض المناقشات الإضافية مع المحددات ، والتي يبدو أنها مجموعة شاملة من 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-redux 's connect لاستخدام إعادة التحديد (أو مكتبة محددات مماثلة) عندما يكون mapStateToProps هو Array ، فيمكننا تشجيع استخدام المحددات وجعلها مريحة للغاية دون كسر التوافق. لا أعتقد أن هذه المكتبة يجب أن تقترن بـ React أو react-redux بالضرورة ، ولكن ربما يمكننا التعامل مع هذا التمدد من خلال خيار react-redux أو تقديم حزمة أخرى تغلف مجموعة المبتدئين بـ react-redux دعم

نعم ، أنا لا أتطلع إلى فعل أي شيء باستخدام React-Redux من أجل MVP الأولي.

في هذه الحالة ، هل هناك طريقة جيدة لإضافة تجريد للمحددات على مستوى Redux أم أن هذا شيء لا يمكننا القيام به بشكل فعال إلا فوق رد الفعل والإعادة؟ المشكلة هي أننا لا نريد أن يكون هذا غير متوافق مع رد الفعل والإعادة ، لذلك أعتقد أنه إذا لم يكن ذلك ممكنًا ، فيجب علينا التخلص من المحددات في الوقت الحالي.

طالما أنها تنفذ واجهة برمجة تطبيقات المتجر ، فهي متوافقة مع رد الفعل والإعادة. نحن لا نتطلع إلى كسر واجهة برمجة التطبيقات هذه ، فقط تحسين DX.

منطقي. لم أستخدم المحددات خارج رد الفعل ، لذا كنت أتساءل عما إذا كانت قابلة للتطبيق لتكوين Redux نفسه هنا.

timdorr +1 على الرغبة التي تم التعبير عنها من خلال أزواج مخفض / عمل أسهل. أرغب أيضًا في تقديم طريقة ما لتسهيل إنشاء وحدة إعادة الإرسال (ويعرف أيضًا باسم نمط البط) بحيث يكون إنشاء مخفض ومنشئي عمل ومحددات تجربة ممتعة أكثر وأسهل في الاستخدام.

أعتقد أن إيجاد حل لهذه المشكلة يجعل غالبية الناس سعداء سيتطلب المزيد من التخلص من الدراجات وأنا أتساءل عما إذا كان هذا شيئًا يمكننا إضافته في إصدار متابعة بحيث لا يحظر أولًا إفراج.

أعتقد أن ما أنشأه markerikson في تعليقه يقلل بالفعل من قدر كبير من

بعد ذلك ، يمكننا معالجة الجوانب الأخرى من Redux المرهقة (إنشاء إعادة / إجراء / محدد).

أعتقد أن محاولة حل جميع المشكلات مقدمًا ستعيق تحقيق أي شكل من أشكال التقدم الملموس.

إذا كنت تعتقد أنه جاهز بما فيه الكفاية ، فأعتقد أنه سيكون فكرة جيدة أن تبدأ مستودعًا حتى نتمكن من اختبار هذا الإعداد باستخدام رمز المثال والتطبيق التجريبي قليلاً (أو ربما حزمة في فرع ميزة في monorepo ، ويمكننا ذلك التعاون من خلال العلاقات العامة).

بالتأكيد. سأرى ما إذا كان بإمكاني الحصول على شيء ما في وقت لاحق اليوم.

لا نحتاج إلى مستودع آخر. سيكون هذا موجودًا داخل الحالي. الرجاء جعل أي شيء العلاقات العامة أولا.

هل يجب أن يكون هذا جزءًا من الحزمة الرئيسية redux كاستيراد منفصل (لذلك هذا متوافق تمامًا مع العودة) أم تفضل monorepo مع حزم متعددة؟ أعتقد أن الأول سيكون كافيًا ، يمكننا دائمًا استخدام تصدير ملف آخر دون إنشاء حزمة جديدة إذا كانت كبيرة جدًا.

أود أن ألعب بهذا كإعادة / حزمة منفصلة لتبدأ بها ، حقًا.

قد يكون من الأسهل استخدام إعداد الأدوات الحالي في هذا الريبو لأن دمجه مرة أخرى في المستقبل قد يكون عرضة للخطأ. ربما لا نحتاج أيضًا إلى دعم بناء جملة مختلف لأننا لا نجعل React محددة.

إذا كان الملف واحدًا مع بعض التهيئة المسبقة ، فسيكون الاحتفاظ به هنا أسهل. بسبب التبعيات ، يجب أن تكون حزمة منفصلة. نحن لا نريد تحميل التطبيقات الموجودة بهؤلاء.

مرة أخرى ، لا أعتقد أننا بحاجة إلى استخدام monorepo ، ولكن يمكننا الحصول على مجلد للبنيات المجمعة المحددة إذا بدأنا في إنشاء أكثر من واحد. مجرد مجلد starter في الوقت الحالي بحزمته الخاصة. يجب أن يقوم json بالمهمة.

تعجبني فكرة الاحتفاظ بهذه الحزمة محليًا في حزمة redux الرئيسية إذا كانت تستخدم فقط الكود المحلي لإعادة نفسها. أصبح أكثر ترددًا إذا بدأنا في جذب التبعيات الخارجية لدعم الأفكار التي تم التعبير عنها هنا.

أعتقد أن بعض التبعيات الخارجية مثل immer و thunk / promation و reelect ستكون لا تقدر بثمن لأهدافنا هنا وتستحق التبعيات الإضافية للمبتدئين ، على الرغم من أننا قد لا نريد تلك التبعيات على الحزمة الرئيسية redux نفسها .

لذا ، آه ... ذهبت وفعلت شيئًا:

الأشياء التي تختلف عن المقتطف سابقًا:

  • لقد طرحت خيار التكوين enhancers ، فقط لأن
  • أضفت التبعية selectorator وقمت بتصدير createSelector

أفكار؟

بصفتي شخصًا علمت نفسي للتو Redux (و React) في الأسبوعين الماضيين ، لا أطيق الانتظار لرؤية المنتج النهائي. أنا متأكد من أنني سأمتلك الكثير من الأشياء لتنظيفها في الكود الخاص بي.

😏 👍

لذلك ، نظرًا لأن الفكرة الطويلة هي تبسيط استخدام redux ، يمكنني اقتراح لحظتين:

  1. أضف دالة الإنشاء إلى expect(mapStateToProps(state)).toEqual(mapStateToProps(state)) حرفياً. فقط لتشجيع الناس على إنشاء كود أفضل. لم أشاهد اختبارات مثل هذه من قبل ، لكن الخريطة ليست نقية جدًا ، ستاتيتوبروبس هي إحدى مشكلات إعادة الإرسال.

  2. فكر في تبني شيء مثل memoize-state . إنه مثل Immer.js للمحددات. النقطة الأساسية - يمكن للعميل فقط كتابة mapStateToProps أو المحدد بالشكل الذي يفضله ، وتذكره. حتى أنه يمكنه حل مشكلة إعادة التحديد هذه من خلال "مشاركة المحددات مع الدعائم عبر مثيلات مكونات متعددة" دون فقد الذاكرة "الشائعة" بين الحالات. فقط قم بتذكير الأشياء

  1. أرى ما تقصده من حيث التوصية بالمحددات النقية ، ولكن لا يزال بإمكان المحدد غير النقي غير الفعال اجتياز هذا الاختبار. أنا أحب الاقتراح الثاني أكثر.
  2. هذا يبدو رائعًا ، لذلك قمنا فقط بلف المحددات بنفس الطريقة التي نلف بها مخفضات السرعة ، أليس كذلك؟

ومع ذلك ، كما ناقشنا أعلاه ، هذا هو رد فعل - إعادة إحياء أكثر من شيء سيكون في حزمة البداية وهو غير مقدر لـ React.

هذا حقا رائع!

لدي طلب واحد / قليل من التعليقات ، رغم ذلك ؛ أفضل إذا لم يتم استخدام Immer بشكل ضمني.

إمر عظيم . لقد أصبح أحد المرافق المفضلة لدي. ولكن حتى عند استخدامه بشكل صريح ( produce(baseState, draftState => ... ) ، أشعر بالقلق عندما يقوم أشخاص آخرون ليسوا على دراية به بعرض الكود الخاص بي ، ولا يدركون أنه لا يمكنني القيام بهذه الأشياء الطفرية إلا بسبب قوى Immer الخارقة.

بالطريقة التي تبدو بها واجهة برمجة التطبيقات الآن ، يمكنني أن أتخيل أن الوافدين الجدد لا يدركون أن حالة الإعادة يجب أن تكون ثابتة. أعتقد أن سوء الفهم قد يعضهم بشدة عندما يحاولون استخدام 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.

بالطريقة التي تبدو بها واجهة برمجة التطبيقات الآن ، يمكنني أن أتخيل أن الوافدين الجدد لا يدركون أن حالة الإعادة يجب أن تكون ثابتة. أعتقد أن سوء الفهم قد يعضهم بشدة عندما يحاولون استخدام Redux بدون مجموعة المبتدئين هذه.

في رأيي ، يجب أن نوصي بعدم استخدام Redux مباشرةً لصالح هذه الحزمة عند اكتمالها بسبب https://github.com/reactjs/redux/issues/2858. نريد في الأساس إما تحذير المستخدمين أو حمايتهم من جميع الطفرات افتراضيًا ، ولكن لا يمكننا القيام بذلك بسهولة في النواة دون كسر الأشياء ، لذلك يجب أن نوصي بعدم استخدام النواة إلا في حالات الحافة حيث لا تكون مجموعة المبتدئين كافية. هذا مشابه لكيفية توصية React باستخدام CRA و Redux توصي بإعادة رد الفعل عند استخدام React.

أرى أن createNextState هو تصدير بالفعل ، فلماذا لا نشجع المستخدمين على استخدامه صراحة:

ليست فكرة سيئة ، لكنني أعتقد أننا نفضل أن نكون ضمنيًا هنا خاصةً لأننا لا ننشئ شفرة المصدر وأن إضافة immer تتوافق مرة أخرى.

أرى الكثير من الأشخاص يوصون باستخدام libs مثل immer.js ، والتي من وجهة نظري المتواضعة تتمثل في الانحراف عن غير قصد الدافع للتعلم واحترام متطلبات store .

نعلم جميعًا أنه لا يمكن تغيير المتجر ، وبالتالي ، أفضل أن يكون لدي آلية تحقق حيث يتحقق من مثيل newState مقابل ( === ) previousState وإذا كانت هي نفس الحالة ، فإن ذلك يؤدي إلى حدوث خطأ.

بهذه الطريقة سيتم إجبار الجميع على تعلم قواعد ومتطلبات store .

ملاحظة: أنا أتفهم حقًا فائدة immer وليس لدي أي شيء ضدها على الإطلاق ، لكننا نصل إلى وقت يفهم فيه الناس المفهوم أخيرًا ، مما قد يولد مصدرًا كبيرًا للارتباك ، ويقولون تقنيًا ، إذا قمنا بقياسها ، فلن نفعل شيئًا سوى إضافة طبقة إضافية من التعقيد فقط لتخفيف المكتبة.

الاقتراحات الشخصية:

يجب إضافة logger و devTools و Thunk كقيمة افتراضية لـ Starter ، أما الباقي فأعتقد أنه اختيار شخصي.

نعلم جميعًا أن المتجر لا يمكن تحوره ، وبالتالي ، فأنا أفضل أن يكون لدي آلية تحقق حيث يتحقق من حالة الحالة الجديدة مقابل (===) الحالة السابقة وإذا كانت هي نفس الحالة ، فإن ذلك يؤدي إلى حدوث خطأ.

هناك حالات حيث لا ترغب في تغيير الحالة بناءً على الإجراء ، لذلك ستعيد نفس مثيل المتجر لحفظ الذاكرة ومنع أي اختلاف إيجابي خاطئ. حتى لو تجاوزنا هذه المشكلة ، يبدو أن Redux لا يريد مدققًا في جوهره وأعتقد أن Immer هو ضمان جيد لهذا الأمر شخصيًا. أوافق على أنه نوع من هزيمة الغرض من تعلم Redux إلى حد ما ، لكنني أرى العديد من المطورين يتعلمون Redux ولا يرغبون في تعلم FP الخالص أو ليسوا على دراية به.

إذا قمنا بقياسها ، فلن نفعل شيئًا سوى إضافة طبقة إضافية من التعقيد فقط لتخفيف المكتبة.

على حد علمي ، فإن الطريقة التي يتم بها تطبيق Immer للوكيل لا تحتوي إلا على عبء في الأداء إذا تم تحويره بالفعل ، لذلك لا ينبغي أن يكون لمخفضات التحديث الثابتة النموذجية عبء في الأداء. أعتقد أن هذا توازن جيد.

يجب إضافة المسجل و devTools و Thunk كإعداد افتراضي لـ Starter ، وأعتقد أن الباقي هو اختيار شخصي.

هناك بعض الأشياء الأخرى التي أود التفكير في إزالتها (على الرغم من أنني شخصيًا لا أرى ميزة كبيرة للمسجل على أدوات المطور التي تعوض عن زيادة الأداء) ، راجع https://github.com/markerikson/ 19- مجموعة إعادة بدء التشغيل / القضايا /. ومع ذلك ، فأنا لا أعارض إضافة المزيد من الأشياء إذا كانت متوافقة مرة أخرى مثل استخدامنا الحالي لـ Immer و Thunk.

هناك حالات حيث لا ترغب في تغيير الحالة بناءً على الإجراء ، لذلك ستعيد نفس مثيل المتجر لحفظ الذاكرة ومنع أي اختلاف إيجابي خاطئ. حتى لو تجاوزنا هذه المشكلة ، يبدو أن Redux لا يريد مدققًا في جوهره وأعتقد أن Immer هو ضمان جيد لهذا الأمر شخصيًا. أوافق على أنه نوع من هزيمة الغرض من تعلم Redux إلى حد ما ، لكنني أرى العديد من المطورين يتعلمون Redux ولا يرغبون في تعلم FP الخالص أو ليسوا على دراية به.

nickmccurdy أفهم تمامًا وجهة نظرك ، وأنا أوافق على أنه لا ينبغي أن يكون لدينا عائق في التعلم بسبب بعض مفاهيم FP و Mutation وما إلى ذلك ... ولكن بصفتي معلمًا ، أؤمن بشدة بعدم طلاء المتدرب بالسكر إخفاء التعقيد عنهم. على أي حال ، إنها مجرد مسألة ذوق ، أنا محترف في التعلم والتقدم ، وبالنظر إلى هذا الاقتراح ، تخبرني حدسي بطريقة ما أننا سنمضي قدمًا في القبول ، ولكننا نتراجع مع المعايير. فقط في الملاحظة ، فكر في كل المحتوى الموجود على الويب في الوقت الحالي الذي يُدرس معايير Redux وكيف يتم التقاطه أخيرًا.

على حد علمي ، فإن الطريقة التي يتم بها تطبيق Immer للوكيل لا تحتوي إلا على عبء في الأداء إذا تم تحويره بالفعل ، لذلك لا ينبغي أن يكون لمخفضات التحديث الثابتة النموذجية عبء في الأداء. أعتقد أن هذا توازن جيد.

عندما أقصد إضافة طبقة من التعقيد ، أعني أن Immer لم يكن موجودًا من قبل ، والآن يمكن أن يكون كذلك ، سيتعين علينا دعمه في المكتبة ، والاختبار ، وتقييم مشكلات الأداء ، وأخيرًا وليس آخرًا هذا القسم هنا يجعلني أشعر بالقلق:

Immer.js - التجميد التلقائي
يقوم Immer تلقائيًا بتجميد أي أشجار حالة يتم تعديلها باستخدام المنتجات. هذا يحمي من التعديلات العرضية لشجرة الحالة خارج المنتج. يأتي هذا مع تأثير على الأداء ، لذلك يوصى بتعطيل هذا الخيار في الإنتاج. يتم تمكينه افتراضيًا. يتم تشغيله بشكل افتراضي أثناء التطوير المحلي ، ويتم إيقاف تشغيله في الإنتاج. استخدم setAutoFreeze (صواب / خطأ) لتشغيل هذه الميزة أو إيقاف تشغيلها بشكل صريح.

وفجأة الآن نحتاج أيضًا إلى دعم الميزات المضافة في Development / Prod . إنه مجرد قدر كبير من العمل ومثير للقلق لأنه ليس هناك الكثير من المقايضة ، ولكن مرة أخرى ، هذا مجرد رأيي الشخصي.

codedavinci : الهدف من هذه المكتبة redux-starter-kit هو إضافة أدوات مفيدة وتجريد أعلى عملية إعداد متجر Redux "الأساسي". لاحظ أيضًا أن هذا _ لا _ ينتقل إلى Redux core نفسه ، بل في مكتبة منفصلة نود أن نجعلها جزءًا "رسميًا" من Redux org في النهاية.

ستعمل جميع أكواد Redux الموجودة لديك. ستظل جميع البرامج التعليمية الموجودة على ما يرام. نحن نحاول فقط إضافة نهج أبسط مدعوم رسميًا لإعداد واستخدام Redux.

markerikson أنا أفهم الهدف المتمثل في الحصول على مجموعة المبتدئين وأنا متوقفة تمامًا عن كل ما هو مذكور أعلاه ، فقط مقاومة قليلاً لامتلاك lib مثل Immer.js الذي يغير مفهوم المكتبة ، سيتعلم الناس في النهاية starter-kit وتجاهل المفاهيم الأساسية تمامًا. لا يوجد تغيير في المتجر هو الشعار ، لقد كان Redux يبيعه دائمًا ، إنه جزء من العلامة التجارية.

ملاحظة: أفهم تمامًا أن Immer.js لا يغير أي شيء ، بل يساعدك على عدم القيام بذلك ، أنا فقط أتحدث فقط عن المعايير التركيبية المسموح بها مثل push ، splice ...

ربما ، أنا فقط أقاوم التغييرات :)

codedavinci : نعم ، أفهم الهدف من المخاوف. ومع ذلك ، فإن إحدى الشكاوى الشائعة حول Redux هي ألم كتابة كود تحديث مناسب غير قابل للتغيير ، وإيمير هي ببساطة أفضل مكتبة رأيتها لتبسيط تلك التحديثات.

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 مجموعة من العلاقات العامة في انتظار المناقشة والاندماج ، معظمهم حول الأدوات ، ولكن أيضًا بعض النقاش حول كيف نريد تركيز المشروع على المدى الطويل. أحتاج إلى الالتفاف حول هذه الأشياء ، لكنني كنت مشغولًا بأشياء أخرى في الأسابيع القليلة الماضية (بما في ذلك محاضرة المؤتمر التي سأقدمها غدًا).

تقدم كبير nickmccurdy & markerikson 👍 أحب بساطته وفعاليته. لاحظت nickmccurdy أنك نشط جدًا في المشروع ، وأحب إجراء محادثة معك حول بعض الأفكار ، واسمحوا لي أن أعرف إذا كنت ترغب في ذلك! :)

بالتأكيد شكرًا ، ربما يكون من الأفضل بدء مناقشة مفتوحة في عدد جديد ولكن يمكنك التواصل معي مباشرةً عبر [email protected] أو على

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

وهو شيء مشترك لا يسمح لي المخفضون بالقيام به حقًا.

@ abradley2 : نحن لا نخطط لإزالة combineReducers من قلب Redux ، إذا كان هذا هو ما تطلبه. لكن نعم ، لقد قلنا دائمًا أن combineReducers هو أداة مساعدة لحالة الاستخدام الأكثر شيوعًا ، وأنه يتم تشجيعك على كتابة منطق مخفض مخصص لموقفك الخاص.

لدينا اسم الحزمة redux-starter-kit ، وتم نقل الريبو إلى المؤسسة على https://github.com/reduxjs/redux-starter-kit . سأغلق هذا الموضوع. يمكن أن تحدث أي مناقشة أخرى في هذا الريبو.

أيضًا ، بدأت العمل على إضافة فحوصات الطفرات والتسلسل افتراضيًا.

هل كانت هذه الصفحة مفيدة؟
0 / 5 - 0 التقييمات