Tại sao các hàm trạng thái của Redux được gọi là bộ giảm?


82

Đây là một phần trong tài liệu Redux chính thức :

Nó được gọi là bộ giảm tốc vì đây là loại hàm bạn sẽ chuyển đến Array.prototype.reduce(reducer, ?initialValue)

Nó không có nhiều ý nghĩa đối với tôi. Ai đó có thể giải thích cho tôi tại sao chúng thực sự được gọi là bộ giảm tốc? Thực tế là chúng trả về một giá trị mặc định (hoặc chúng có giá trị đối số mặc định) không làm cho chúng giảm IMHO.


6
Chúng là bộ giảm chính xác vì chúng hoạt động giống như hàm mà bạn chuyển đến reduce, có quyền truy cập vào giá trị mặc định và một giá trị khác, đồng thời trả lại cho bạn giá trị mặc định đã được chuyển đổi tiềm năng của bạn. state -> action -> state
azium

2
một bông hồng có tên khác ... có thể là tiếp thị; bản đồ / giảm là một từ thông dụng bây giờ ...
dandavis

1
đó là lý do tại sao bạn phải bắt đầu tự suy nghĩ và không dựa vào khuôn khổ. Một framwork chủ yếu là công việc của một hoặc một vài nhà phát triển với tầm nhìn riêng của họ về cách giải quyết một vấn đề được người dùng internet thích ứng. Một số khung làm việc đúng nhưng hầu hết thì không. một nụ hôn rực rỡ, dù ít hay nhiều không phải là một giải pháp. Đây chỉ là một ví dụ trong số nhiều trường hợp ngoài kia.
Codebeat

Câu trả lời:


71

Thực tế là chúng trả về một giá trị mặc định (hoặc chúng có giá trị đối số mặc định) không làm cho chúng giảm IMHO.

Các bộ giảm thiểu không chỉ trả về các giá trị mặc định. Chúng luôn trả lại sự tích lũy của trạng thái (dựa trên tất cả các hành động trước đó và hiện tại).

Do đó, chúng hoạt động như một bộ giảm bớt trạng thái. Mỗi khi một bộ giảm redux được gọi, trạng thái được chuyển vào cùng với hành động (state, action). Trạng thái này sau đó được giảm (hoặc tích lũy) dựa trên hành động, và sau đó trạng thái tiếp theo được trả lại. Đây là một chu kỳ của cổ điển foldhoặc reducechức năng.

Như @azium đã tổng kết state -> action -> state.


7
Humm theo logic này không phải chúng được gọi là bộ tăng hơn là bộ giảm? Không có dữ liệu là bao giờ bị giảm phúc của mình thêm: / lol
Jamie Hutber

16
@JamieHutber Tôi nghĩ bạn hơi thiếu ý nghĩa của từ giảm bớt trong ngữ cảnh này. giảm tốc là lấy một luồng (hoặc tập hợp) các mục và kết hợp chúng thành một mục duy nhất. Trong trường hợp này, tất cả các hành động (xuyên thời gian) là tập hợp các mục và trạng thái là một mục duy nhất. Có lý?
Davin Tryon

7
lol tôi thấy bây giờ. Vì vậy, về cơ bản nó chỉ nối chúng. Tại sao không gọi nó là sáp nhập sau đó: Cảm ơn P để làm cho nó rõ ràng với tôi :)
Jamie Hutber

20
Cảm ơn trời đất, tôi không phải là người duy nhất nghĩ rằng việc giảm bớt tên là một chút giảm ít nhất 2.000 lượt xem trên bài đăng này tại thời điểm tôi viết bài này. Thực tế là ai đó thậm chí còn sẵn sàng bỏ công sức ra để tìm hiểu lý do tại sao nó được gọi là bộ giảm tốc, nó không ngụ ý nó thực sự là một chút sao? Nếu Nó được gọi là bộ giảm vì đó là loại hàm bạn sẽ truyền cho Array.prototype.reduce, thì nó giống như chúng ta gọi quả cam là máy ép trái cây vì chúng ta chuyển màu cam cho object.prototype.juicer, hay chúng ta không nên gọi nó là quả?
Yini

2
Tôi đồng ý, nó hoàn toàn không phải là một cái tên trực quan. Về mặt logic, để được gọi là giảm thiểu, nó phải giảm bớt một số thứ. Nếu cần một loạt các thay đổi trạng thái cùng với một trạng thái và kết hợp chúng thành một trạng thái duy nhất cùng một lúc, thì đó sẽ là một cái tên trực quan.
Peter Evan Thỏa thuận

20

Nếu bạn coi chuỗi hành động trong ứng dụng của mình giống như một danh sách hoặc có thể giống một luồng hơn, thì điều đó có thể có ý nghĩa hơn.

Lấy ví dụ giả định này:

['apple', 'banana', 'cherry'].reduce((acc, item) => acc + item.length, 0)

Đối số đầu tiên là một hàm của biểu mẫu (Int, String) => Int. Cùng với một giá trị ban đầu, bạn chuyển reducecái có thể được gọi là "hàm giảm thiểu" và bạn nhận được kết quả của việc xử lý chuỗi các mục. Vì vậy, bạn có thể nói, hàm giảm thiểu mô tả những gì được thực hiện với từng mục riêng lẻ liên tiếp để thay đổi kết quả. Nói cách khác, hàm giảm thiểu lấy giá trị đầu ra trước đó và giá trị tiếp theo, và nó sẽ tính toán đầu ra tiếp theo.

Điều này tương tự như những gì một bộ giảm thiểu Redux làm: nó nhận trạng thái trước đó và hành động hiện tại, và nó tính toán trạng thái tiếp theo.

Trong phong cách lập trình chức năng thực sự, bạn có thể xóa bỏ ý nghĩa được áp dụng cho các đối số và kết quả, và chỉ tập trung vào "hình dạng" của các đầu vào và đầu ra.

Trong thực tế, các bộ giảm Redux thường trực giao, theo nghĩa là đối với một hành động nhất định, chúng không thực hiện thay đổi tất cả các thuộc tính giống nhau, điều này giúp dễ dàng phân chia trách nhiệm và tổng hợp đầu ra combineReducers.


Vâng, bạn nói đúng, sẽ có ý nghĩa hơn khi tôi nghĩ về các hành động giống như về một luồng. Tuyệt vời, hãy tận dụng điều đó!
Anton Savchenko

Đây là cách tôi bước đầu hiểu nó, nhưng điều này dường như không có cách nào trong những triển khai cửa hàng tôi đã nhìn thấy vậy, đến nay đã thực hiện nó ...
Boris Callens

16

Như đã đề cập, tên liên quan đến khái niệm bộ giảm tốc trong lập trình chức năng. Bạn cũng có thể thấy định nghĩa của từ điển Merriam-Webster về bộ giảm tốc hữu ích:

1a. để thu hút cùng nhau hoặc nguyên nhân để hội tụ: hợp nhất (giảm tất cả các câu hỏi thành một)

Bộ giảm tốc hợp nhất các hành động thành một đối tượng duy nhất đại diện cho trạng thái ứng dụng.


8

Lý do tại sao bộ giảm redux được gọi là a reducerlà vì bạn có thể "giảm" a collection of actionsvà một initial state(của cửa hàng) để thực hiện các hành động này để có được kết quả final state.

Làm sao? Để trả lời điều đó, hãy để tôi định nghĩa lại một bộ giảm tốc:

Phương thức Reduce () áp dụng một function (reducer)đối với một accumulatorvà mỗi giá trị của mảng (từ trái sang phải) để giảm nó thành một giá trị duy nhất.

Và một bộ giảm redux làm gì?

Bộ giảm thiểu là một thuần túy functionlấy trạng thái hiện tại và một hành động, và trả về trạng thái tiếp theo. Lưu ý rằng trạng thái là accumulatedkhi mỗi hành động trên bộ sưu tập được áp dụng để thay đổi trạng thái này.

Vì vậy, cho trước a collection of actions, giảm được áp dụng trên mỗi giá trị của tập hợp (từ trái sang phải). Lần đầu tiên, nó trả về initial value. Bây giờ bộ giảm được áp dụng lại trên trạng thái ban đầu này và hành động đầu tiên để trả về trạng thái tiếp theo. Và mục bộ sưu tập tiếp theo (hành động) được áp dụng mỗi lần trên current stateđể lấy next statecho đến khi nó đến cuối mảng. Và sau đó, bạn nhận được the final state. Thật tuyệt làm sao!


5

Tác giả nghĩ rằng trạng thái như là bộ tích lũy của chức năng giảm. Ví dụ:

Final State = [Action1, Action2, ..., ActionN].reduce(reducer, Initial State);

Chức năng giảm đến từ Lập trình chức năng, tên "giảm thiểu" cũng đến từ FP.

Tôi không thích sử dụng tên đó ở đây. Bởi vì tôi không xem thế giới là một kết quả giá trị duy nhất sau các hành động. Trạng thái ở đây là một đối tượng. Ví dụ:

['eat', 'sleep'] === [addTodo('eat'), addTodo('sleep')].reduce(reducer, []);

Đây Giảm giảm gì cả. Và tôi không quan tâm nó có giảm được gì hay không. Đặt tên nó là Transducer sẽ có ý nghĩa hơn.


5

Chúng tôi biết các Bộ giảm thiểu đến từ đâu (lập trình chức năng) và tại sao chúng có thể được coi là đang thực hiện công việc giảm bớt (giảm n mục đầu vào thành một giá trị trả về duy nhất - đó chỉ là những gì các hàm thông thường được cho là làm). Tuy nhiên: Tên chỉ là một cái tên, giống như hoa hồng là tên của một loài hoa hồng. Không suy nghĩ quá nhiều. Các chuyên gia lập trình của Redux là những người làm công nghệ thông tin, họ bị khóa trong bối cảnh của mình và điều đó có ý nghĩa. Phần còn lại của chúng tôi phải chấp nhận quyền của nhà phát minh để gọi một con chó xanh là một con mèo vàng ;-)


2

Làm thế nào về chúng tôi gọi nó là Deducer từ bây giờ. Nó suy ra trạng thái mới dựa trên trạng thái trước đó và hành động đến.


1

Chúng không nên được gọi là giảm vì giảm có nghĩa là tạo ra ít hơn, các chức năng này thường tạo ra nhiều hơn. và sau đó trả lại nó


1

Tôi không thể thấy cách một trình giảm Redux ánh xạ trực tiếp đến hàm bạn sử dụng reduce, vì vậy đây là một vài ví dụ để xem chúng khớp với nhau như thế nào.

Đầu tiên là hàm giảm tiêu chuẩn (được gọi là 'tích lũy' trong MDN) từ tài liệu MDN Array.reduce và sau đó là một ví dụ đơn giản của Dan Abramov Counter.jsở cuối bài đăng blog 'Bạn có thể không cần Redux' của anh ấy .

  • sum thêm một giá trị vào bộ tích lũy
  • reducer cộng / trừ một giá trị vào / từ bộ tích lũy.

Trong cả hai trường hợp ở đây, 'trạng thái' chỉ là một số nguyên.

Bạn đang 'tích lũy' các hành động vào trạng thái. Đây cũng là cách bất biến để sửa đổi bất kỳ đối tượng JavaScript nào.

const sum = function(acc, val) {
    return acc + val;
};

const reducer = function(state, action) {
    switch (action) {
        case 'INCREMENT':
            return state + 1;
        case 'DECREMENT':
            return state - 1;
        default:
            return state;
    }
};

console.log('sum', [1, -1, 1].reduce(sum, 0));

console.log('reduce', ['INCREMENT', 'DECREMENT', 'INCREMENT'].reduce(reducer, 0));

console.log('sum', [1, 1, 1].reduce(sum, 0));

console.log('reduce', ['INCREMENT', 'INCREMENT', 'INCREMENT'].reduce(reducer, 0));


0

Các câu trả lời khác giải thích rõ tại sao nó được đặt tên như vậy nhưng chúng ta hãy thử đặt tên cho nhiều thứ hơn ...

const origState = 0;
const actionOperators = {
    increment: (origState) => origState++,
    decrement: (origState) => origState--,
};
const anOperator = (aState, anAction) => actionOperators[anAction](aState);
const actions = ['increment', 'decrement', 'increment'];
const finalState = actions.reduce(anOperator, origState);

Đầu tiên, reducecó thể được gọi use anOperator with every action name and accumulated state, starting with origState. Trong smalltalk, nó được gọi là actions inject: origState into: anOperator. Nhưng những gì thực sự bạn tiêm vào nhà điều hành? OrigState VÀ các tên hành động. Vì vậy, ngay cả trong tên phương thức Smalltalk cũng không rõ ràng lắm.

actionOperators[increment]là một Trình giảm, nhưng tôi muốn gọi nó là actionOperator vì nó được triển khai cho mỗi hành động. Trạng thái chỉ là một đối số (và một đối số khác là giá trị trả về).

Tuy nhiên, Reducer là một từ tốt hơn để có mặt trên kết quả tìm kiếm của google. Nó cũng tương tự như Redux.


0

Trong đoạn mã dưới đây, bạn chỉ cần nghĩ về bộ tích lũy là các hành động và currentValue là một trạng thái trong ngữ cảnh redux. với ví dụ này, bạn sẽ tìm ra lý do tại sao họ đặt tên nó là một bộ giảm tốc.

const array1 = [1, 2, 3, 4];
const reducer = (accumulator, currentValue) => accumulator + currentValue;

// Main operation is 1 + 2 + 3 + 4 = 10
// but think of it as a stack like this: 

// | 2 | | 3 | | 4 | 
// |_1_| |_3_| |_6_| | 10 | => the 10 is in result

console.log(array1.reduce(reducer));
// expected output: 10

Phương thức Reduce () thực thi một hàm giảm thiểu (mà bạn cung cấp) trên mỗi phần tử của mảng, dẫn đến một giá trị đầu ra duy nhất.

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.