Redux: В документе `combReducers` не объясняется, как понять, какую часть состояния передать редуктору.

Созданный на 8 авг. 2015  ·  7Комментарии  ·  Источник: reduxjs/redux

Новый документ combReducers в порядке, но он не объясняет, что вы должны называть reducer стороной государства, которым он управляет.

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

Спасибо за отзыв, это очень ценно.

Я хочу подчеркнуть, что

Соглашения являются частью API

не совсем правда.

Вероятно, нам следует просто избегать import * в документации, потому что люди считают, что это неотъемлемая часть API, когда его совсем нет, и это просто удобный ярлык, который я использую.

Имена функций имеют значение только из-за того, как работают ES6 export и import * as .

Кстати, я все еще не понимаю, как передать часть состояния редуктору. Мне к ним присоединиться camelCase или что-то в этом роде? state = {owner: {name: 'John'}} → функция экспорта ownerName (state = [], действие)?

Нет :-). Это не волшебный API. combineReducers(object) объединяет несколько редукторов в один и передает части состояния своим значениям с помощью предоставленных вами ключей. Он делает это ровно на один уровень в глубину. Нет никакой «магии построения целого дерева». Вам решать, как разделить редюсер на несколько функций:

// Function names don't matter!
function processA(state, action) { ... }
function doSomethingWithB(state, action) { ... }

function reducer(state = {}, action) {
  return {
    // Because you call them!
    a: processA(state.a, action),
    b: doSomethingWithB(state.b, action)
  };
}

// Not using combineReducers
let store = createStore(reducer);

Они даже не имеют значения, если вы используете помощник combineReducers если вы сами создаете объект :

// Function names don't matter!
function processA(state, action) { ... }
function doSomethingWithB(state, action) { ... }

/*
function reducer(state = {}, action) {
  return {
    a: processA(state.a, action),
    b: doSomethingWithB(state.b, action)
  };
}
*/
let reducer = combineReducers({
  a: processA,
  b: doSomethingWithB
});

let store = createStore(reducer);

Вы можете делать это много раз.

До:

// Function names don't matter!
function processSomePartOfA(state, action) { ... }
function doSomethingWithOtherPartOfA(state, action) { ... }

function processA(state, action) {
  return {
    // Because you call them!
    somePart: processSomePartOfA(state.somePart),
    otherPart: doSomethingWithOtherPartOfA(state.otherPart)
  }
}
function doSomethingWithB(state, action) { ... }

function reducer(state = {}, action) {
  return {
    // Because you call them!
    a: processA(state.a, action),
    b: doSomethingWithB(state.b, action)
  };
}

// Not using the helper
let store = createStore(reducer);

Понимаете? Это просто функции, вызывающие функции. Никаких волшебных «глубинных вещей».
И вы также можете использовать combineReducers много раз:

// Function names don't matter!
function processSomePartOfA(state, action) { ... }
function doSomethingWithOtherPartOfA(state, action) { ... }

/*
function processA(state, action) {
  return {
    somePart: processSomePartOfA(state.somePart),
    otherPart: doSomethingWithOtherPartOfA(state.otherPart)
  }
}
*/
let processA = combineReducers({
  somePart: processSomePartOfA,
  otherPart: doSomethingWithOtherPartOfA
});

function processA(state, action) { ... }
function doSomethingWithB(state, action) { ... }

/*
function reducer(state = {}, action) {
  return {
    a: processA(state.a, action),
    b: doSomethingWithB(state.b, action)
  };
}
*/
let reducer = combineReducers({
  a: processA,
  b: doSomethingWithB
});

let store = createStore(reducer);

Единственная часть, где имена функций имеют значение, - это когда вы используете export + import * as для «получения» объекта, который вы передаете combineReducers потому что _так же import * работает_ ! Он помещает вещи в объект на основе их ключей экспорта.

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

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

Это как бы говорит, если вы прочитаете это полностью, не пропуская:

Результирующий редуктор вызывает каждый дочерний редуктор и собирает их результаты в один объект состояния. Форма объекта состояния соответствует ключам переданных редукторов.

Но я согласен, что это должно быть более заметным, поскольку люди часто пропускают это предложение.
Помогут ли вам изменения с # 399?

Я бы предпочел меньше компьютерных знаний, подробное замечание об этом соглашении сразу после примера:

Обратите внимание, что редукторы называются todos и counter - точно так же, как части состояния, которые мы им передаем.

Чтобы передать часть состояния редуктору, Redux использует _convention_ - редуктор должен называться точно так

Я думаю, что № 399 - это хорошо, но это объяснение для _Flux users_. Я еду в Редукс прямо с лодки. Некоторая форма моего текста была бы более полезной для случайных разработчиков JavaScript.

Важная идея здесь: Соглашения являются частью API . Не менее важно createRedux , createDispatcher и любые другие функции API. Всегда явно указывайте соглашения, потому что они являются частью API.

Кстати, я все еще не понимаю, как передать часть состояния редуктору. Мне к ним присоединиться camelCase или что-то в этом роде? state={owner: {name: 'John'} }export function ownerName(state = [], action) ?

Спасибо за отзыв, это очень ценно.

Я хочу подчеркнуть, что

Соглашения являются частью API

не совсем правда.

Вероятно, нам следует просто избегать import * в документации, потому что люди считают, что это неотъемлемая часть API, когда его совсем нет, и это просто удобный ярлык, который я использую.

Имена функций имеют значение только из-за того, как работают ES6 export и import * as .

Кстати, я все еще не понимаю, как передать часть состояния редуктору. Мне к ним присоединиться camelCase или что-то в этом роде? state = {owner: {name: 'John'}} → функция экспорта ownerName (state = [], действие)?

Нет :-). Это не волшебный API. combineReducers(object) объединяет несколько редукторов в один и передает части состояния своим значениям с помощью предоставленных вами ключей. Он делает это ровно на один уровень в глубину. Нет никакой «магии построения целого дерева». Вам решать, как разделить редюсер на несколько функций:

// Function names don't matter!
function processA(state, action) { ... }
function doSomethingWithB(state, action) { ... }

function reducer(state = {}, action) {
  return {
    // Because you call them!
    a: processA(state.a, action),
    b: doSomethingWithB(state.b, action)
  };
}

// Not using combineReducers
let store = createStore(reducer);

Они даже не имеют значения, если вы используете помощник combineReducers если вы сами создаете объект :

// Function names don't matter!
function processA(state, action) { ... }
function doSomethingWithB(state, action) { ... }

/*
function reducer(state = {}, action) {
  return {
    a: processA(state.a, action),
    b: doSomethingWithB(state.b, action)
  };
}
*/
let reducer = combineReducers({
  a: processA,
  b: doSomethingWithB
});

let store = createStore(reducer);

Вы можете делать это много раз.

До:

// Function names don't matter!
function processSomePartOfA(state, action) { ... }
function doSomethingWithOtherPartOfA(state, action) { ... }

function processA(state, action) {
  return {
    // Because you call them!
    somePart: processSomePartOfA(state.somePart),
    otherPart: doSomethingWithOtherPartOfA(state.otherPart)
  }
}
function doSomethingWithB(state, action) { ... }

function reducer(state = {}, action) {
  return {
    // Because you call them!
    a: processA(state.a, action),
    b: doSomethingWithB(state.b, action)
  };
}

// Not using the helper
let store = createStore(reducer);

Понимаете? Это просто функции, вызывающие функции. Никаких волшебных «глубинных вещей».
И вы также можете использовать combineReducers много раз:

// Function names don't matter!
function processSomePartOfA(state, action) { ... }
function doSomethingWithOtherPartOfA(state, action) { ... }

/*
function processA(state, action) {
  return {
    somePart: processSomePartOfA(state.somePart),
    otherPart: doSomethingWithOtherPartOfA(state.otherPart)
  }
}
*/
let processA = combineReducers({
  somePart: processSomePartOfA,
  otherPart: doSomethingWithOtherPartOfA
});

function processA(state, action) { ... }
function doSomethingWithB(state, action) { ... }

/*
function reducer(state = {}, action) {
  return {
    a: processA(state.a, action),
    b: doSomethingWithB(state.b, action)
  };
}
*/
let reducer = combineReducers({
  a: processA,
  b: doSomethingWithB
});

let store = createStore(reducer);

Единственная часть, где имена функций имеют значение, - это когда вы используете export + import * as для «получения» объекта, который вы передаете combineReducers потому что _так же import * работает_ ! Он помещает вещи в объект на основе их ключей экспорта.

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

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

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

Мы меняем примеры, чтобы явно вызывать combineReducers в reducers/index так что, надеюсь, теперь это будет иметь больше смысла: https://github.com/gaearon/redux/pull/473

Закрытие, поскольку этот вопрос, кажется, лучше рассматривается в текущих документах.
И мы больше не используем import * в документации.

Вы действительно думаете, что внедрение такого неявного поведения - это хорошая практика кодирования?

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

Когда вы пишете фреймворк, такая важная функция, как эта, должна быть легко понятной, что, очевидно, не так, например, "волшебное" ощущение.

PS: Я исхожу из официальной документации Redux: "Это не волшебство"

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