Dữ liệu phản hồi có thể không bị thay đổi khi sử dụng truy cập mảng
9 và 0 của Bộ công cụ Redux tự động sử dụng Immer trong nội bộ để cho phép bạn viết logic cập nhật bất biến đơn giản hơn bằng cách sử dụng cú pháp "mutating". Điều này giúp đơn giản hóa hầu hết các triển khai bộ giảm tốc Show
Bởi vì bản thân Immer là một lớp trừu tượng, điều quan trọng là phải hiểu tại sao Redux Toolkit sử dụng Immer và cách sử dụng nó đúng cách Tính bất biến và ReduxKhái niệm cơ bản về tính bất biến"Mutable" có nghĩa là "có thể thay đổi". Nếu một cái gì đó là "bất biến", nó không bao giờ có thể thay đổi Các đối tượng và mảng JavaScript đều có thể thay đổi theo mặc định. Nếu tôi tạo một đối tượng, tôi có thể thay đổi nội dung của các trường của nó. Nếu tôi tạo một mảng, tôi cũng có thể thay đổi nội dung
Điều này được gọi là biến đổi đối tượng hoặc mảng. Đó là cùng một đối tượng hoặc tham chiếu mảng trong bộ nhớ, nhưng bây giờ nội dung bên trong đối tượng đã thay đổi Để cập nhật các giá trị một cách bất biến, mã của bạn phải tạo các bản sao của các đối tượng/mảng hiện có, sau đó sửa đổi các bản sao đó Chúng ta có thể thực hiện việc này bằng tay bằng cách sử dụng các toán tử trải rộng mảng/đối tượng của JavaScript, cũng như các phương thức mảng trả về các bản sao mới của mảng thay vì thay đổi mảng ban đầu
Bạn muốn biết thêm? Để biết thêm thông tin về cách hoạt động của tính bất biến trong JavaScript, hãy xem
Bộ giảm tốc và cập nhật bất biếnMột trong những quy tắc chính của Redux là bộ giảm tốc của chúng tôi không bao giờ được phép thay đổi giá trị trạng thái ban đầu/hiện tại sự nguy hiểm
Có một số lý do tại sao bạn không được thay đổi trạng thái trong Redux
Vì vậy, nếu chúng tôi không thể thay đổi bản gốc, làm cách nào để trả về trạng thái đã cập nhật? tiền boa Các bộ giảm chỉ có thể tạo các bản sao của các giá trị ban đầu và sau đó chúng có thể thay đổi các bản sao đó
Chúng ta đã thấy rằng chúng ta có thể viết các bản cập nhật bất biến bằng tay, bằng cách sử dụng các toán tử trải rộng mảng/đối tượng của JavaScript và các hàm khác trả về các bản sao của các giá trị ban đầu Điều này trở nên khó khăn hơn khi dữ liệu được lồng vào nhau. Một quy tắc quan trọng của các bản cập nhật không thay đổi là bạn phải tạo một bản sao của mọi cấp độ lồng nhau cần được cập nhật Một ví dụ điển hình về điều này có thể trông giống như
Tuy nhiên, nếu bạn đang nghĩ rằng "viết các bản cập nhật bất biến bằng tay theo cách này có vẻ khó nhớ và khó thực hiện chính xác". Uh, đúng vậy. . ) Viết logic cập nhật bất biến bằng tay rất khó và vô tình thay đổi trạng thái trong bộ giảm tốc là lỗi phổ biến nhất mà người dùng Redux mắc phải Cập nhật bất biến với ImmerImmer là một thư viện đơn giản hóa quá trình viết logic cập nhật bất biến Immer cung cấp một hàm có tên là 1, chấp nhận hai đối số. 2 ban đầu của bạn và chức năng gọi lại. Hàm gọi lại được cung cấp phiên bản "bản nháp" của trạng thái đó và bên trong hàm gọi lại, việc viết mã làm thay đổi giá trị bản nháp là an toàn. Immer theo dõi tất cả các nỗ lực thay đổi giá trị dự thảo và sau đó phát lại các thay đổi đó bằng cách sử dụng các giá trị tương đương không thay đổi của chúng để tạo kết quả an toàn, được cập nhật bất biến
Bộ công cụ Redux và ImmerRedux Toolkit's 9 API sử dụng Immer tự động trong nội bộ. Vì vậy, nó đã an toàn để "biến đổi" trạng thái bên trong bất kỳ hàm giảm chữ hoa chữ thường nào được chuyển đến 9 2Đổi lại, 0 sử dụng 9 bên trong, do đó, việc "biến đổi" trạng thái ở đó cũng an toàn 5Điều này thậm chí còn áp dụng nếu các chức năng rút gọn trường hợp được xác định bên ngoài cuộc gọi 7. Ví dụ: bạn có thể có một chức năng rút gọn trường hợp có thể tái sử dụng, dự kiến sẽ "biến đổi" trạng thái của nó và bao gồm nó khi cần 7Điều này hoạt động vì logic "đột biến" được bao bọc trong phương thức 1 của Immer bên trong khi nó thực thithận trọng Hãy nhớ rằng, logic "đột biến" chỉ hoạt động chính xác khi được bao bọc bên trong Immer. Nếu không, mã đó sẽ thực sự thay đổi dữ liệu Mô hình sử dụng ngâmCó một số mẫu hữu ích cần biết và các vấn đề cần chú ý khi sử dụng Immer in Redux Toolkit Trạng thái đột biến và quay trở lạiImmer hoạt động bằng cách theo dõi các nỗ lực thay đổi giá trị trạng thái được soạn thảo hiện có, bằng cách gán cho các trường lồng nhau hoặc bằng cách gọi các hàm thay đổi giá trị. Điều đó có nghĩa là 2 phải là một đối tượng hoặc mảng JS để Immer có thể thấy các thay đổi đã cố gắng. (Bạn vẫn có thể có trạng thái của một lát cắt là nguyên thủy như chuỗi hoặc boolean, nhưng vì dù sao thì nguyên thủy cũng không bao giờ có thể bị thay đổi, tất cả những gì bạn có thể làm chỉ là trả về một giá trị mới. )Trong bất kỳ bộ giảm trường hợp cụ thể nào, Immer hy vọng rằng bạn sẽ thay đổi trạng thái hiện tại hoặc tự xây dựng một giá trị trạng thái mới và trả về nó, chứ không phải cả hai trong cùng một chức năng. Ví dụ: cả hai đều là bộ giảm tốc hợp lệ với Immer 0Tuy nhiên, có thể sử dụng các bản cập nhật không thay đổi để thực hiện một phần công việc và sau đó lưu kết quả thông qua một "đột biến". Một ví dụ về điều này có thể lọc một mảng lồng nhau 0Lưu ý rằng việc thay đổi trạng thái trong hàm mũi tên có trả về ẩn sẽ phá vỡ quy tắc này và gây ra lỗi. Điều này là do các câu lệnh và lệnh gọi hàm có thể trả về một giá trị và Immer nhìn thấy cả biến đổi đã thử và giá trị mới được trả về và không biết nên sử dụng giá trị nào làm kết quả. Một số giải pháp tiềm năng đang sử dụng từ khóa 0 để bỏ qua việc có giá trị trả về hoặc sử dụng dấu ngoặc nhọn để tạo phần thân cho hàm mũi tên và không có giá trị trả về 1Mặc dù viết logic cập nhật bất biến lồng nhau là khó, nhưng đôi khi việc thực hiện thao tác trải rộng đối tượng để cập nhật nhiều trường cùng một lúc sẽ đơn giản hơn so với việc chỉ định các trường riêng lẻ 2Thay vào đó, bạn có thể sử dụng 1 để thay đổi nhiều trường cùng một lúc, vì 1 luôn thay đổi đối tượng đầu tiên được cung cấp 3Đặt lại và thay thế trạng tháiĐôi khi, bạn có thể muốn thay thế toàn bộ 2 hiện có, vì bạn đã tải một số dữ liệu mới hoặc bạn muốn đặt lại trạng thái về giá trị ban đầusự nguy hiểm Một sai lầm phổ biến là thử chỉ định trực tiếp 4. Điều này sẽ không làm việc. Điều này chỉ trỏ biến 2 cục bộ đến một tham chiếu khác. Điều đó không làm biến đổi đối tượng/mảng 2 hiện có trong bộ nhớ, cũng không trả về một giá trị hoàn toàn mới, vì vậy Immer không thực hiện bất kỳ thay đổi thực tế nàoThay vào đó, để thay thế trạng thái hiện có, bạn nên trả về giá trị mới trực tiếp 4Gỡ lỗi và kiểm tra trạng thái soạn thảoThông thường, bạn muốn đăng nhập trạng thái đang tiến hành từ bộ giảm tốc để xem nó trông như thế nào khi nó đang được cập nhật, chẳng hạn như 7. Thật không may, các trình duyệt hiển thị các phiên bản Proxy đã ghi ở định dạng khó đọc hoặc khó hiểuĐể giải quyết vấn đề này, Immer bao gồm một hàm 8 trích xuất một bản sao của dữ liệu được bao bọc và RTK tái xuất 8. Bạn có thể sử dụng điều này trong bộ giảm tốc của mình nếu bạn cần đăng nhập hoặc kiểm tra trạng thái công việc đang tiến hành 5Thay vào đó, đầu ra chính xác sẽ trông như thế này Immer cũng cung cấp các hàm 0 và 1, giúp truy xuất dữ liệu gốc mà không áp dụng bất kỳ bản cập nhật nào và kiểm tra xem liệu một giá trị đã cho có phải là bản nháp được bao bọc bởi Proxy hay không. Kể từ RTK 1. 5. 1, cả hai đều được tái xuất từ RTKCập nhật dữ liệu lồng nhauImmer đơn giản hóa rất nhiều việc cập nhật dữ liệu lồng nhau. Các đối tượng và mảng lồng nhau cũng được bao bọc trong Proxy và được soạn thảo, đồng thời có thể an toàn khi lấy một giá trị lồng nhau vào biến riêng của nó rồi thay đổi nó Tuy nhiên, điều này vẫn chỉ áp dụng cho các đối tượng và mảng. Nếu chúng tôi kéo một giá trị nguyên thủy vào biến riêng của nó và cố gắng cập nhật nó, Immer sẽ không có gì để bọc và không thể theo dõi bất kỳ cập nhật nào 6Có một gotcha ở đây. . Hầu hết thời gian điều này không thành vấn đề, nhưng có thể có những lúc bạn muốn chèn một giá trị và sau đó cập nhật thêm cho nó Liên quan đến vấn đề này, RTK có thể được sử dụng làm bộ giảm tốc độc lập hoặc chức năng cập nhật "đột biến". Các hàm này xác định liệu có "biến đổi" hay trả về một giá trị mới hay không bằng cách kiểm tra xem liệu trạng thái mà chúng đưa ra có được bao bọc trong bản nháp hay không. Nếu bạn đang tự gọi các hàm này bên trong bộ giảm chữ hoa chữ thường, hãy chắc chắn rằng bạn biết liệu bạn đang chuyển cho chúng giá trị nháp hay giá trị đơn giản Cuối cùng, cần lưu ý rằng Immer không tự động tạo các đối tượng hoặc mảng lồng nhau cho bạn - bạn phải tự tạo chúng. Ví dụ: giả sử chúng ta có một bảng tra cứu chứa các mảng lồng nhau và chúng ta muốn chèn một mục vào một trong các mảng đó. Nếu chúng ta cố gắng chèn vô điều kiện mà không kiểm tra sự tồn tại của mảng đó, logic sẽ bị lỗi khi mảng không tồn tại. Thay vào đó, bạn cần đảm bảo mảng tồn tại trước 7Đột biến trạng thái LintingNhiều cấu hình ESLint bao gồm https. // eslint. quy tắc org/docs/rules/no-param-resign, cũng có thể cảnh báo về các đột biến đối với các trường lồng nhau. Điều đó có thể khiến quy tắc cảnh báo về các đột biến thành 2 trong bộ giảm tốc do Immer cung cấp, điều này không hữu íchĐể giải quyết vấn đề này, bạn có thể yêu cầu quy tắc ESLint bỏ qua các thay đổi đối với tham số có tên 2 8Tại sao Immer được tích hợp sẵnTheo thời gian, chúng tôi đã nhận được một số yêu cầu biến Immer thành một phần tùy chọn trong API 0 và 9 của RTK, thay vì yêu cầu nghiêm ngặtCâu trả lời của chúng tôi luôn giống nhau. Bắt buộc phải nhập vai trong RTK và điều đó sẽ không thay đổi Thật đáng để xem xét lý do tại sao chúng tôi coi Immer là một phần quan trọng của RTK và tại sao chúng tôi sẽ không biến nó thành tùy chọn Lợi ích của ImmerImmer có hai lợi ích chính. Đầu tiên, Immer đơn giản hóa đáng kể logic cập nhật bất biến. . Nhìn chung, các hoạt động dài dòng đó rất khó đọc và cũng làm xáo trộn mục đích thực sự của câu lệnh cập nhật là gì. Immer loại bỏ tất cả các trải rộng lồng nhau và các lát mảng. Mã không chỉ ngắn hơn và dễ đọc hơn mà còn rõ ràng hơn nhiều về bản cập nhật thực tế sẽ xảy ra Thứ hai, viết các cập nhật bất biến một cách chính xác rất khó và rất dễ mắc lỗi (chẳng hạn như quên sao chép một cấp độ lồng trong một tập hợp các trải rộng đối tượng, sao chép một mảng cấp cao nhất chứ không phải mục cần cập nhật bên trong mảng, . Đây là một phần lý do tại sao. Immer loại bỏ hiệu quả các đột biến ngẫu nhiên. Không chỉ không có thêm các thao tác trải rộng có thể bị viết sai mà Immer còn tự động đóng băng trạng thái. Điều này gây ra lỗi nếu bạn vô tình thay đổi, ngay cả bên ngoài bộ giảm tốc. Loại bỏ nguyên nhân số 1 gây ra lỗi Redux là một cải tiến lớn Ngoài ra, Truy vấn RTK sử dụng các khả năng vá lỗi của Immer để kích hoạt các bản cập nhật tối ưu và cập nhật bộ đệm thủ công. Đánh đổi và mối quan tâmGiống như bất kỳ công cụ nào, việc sử dụng Immer cũng có sự đánh đổi và người dùng đã bày tỏ một số lo ngại về việc sử dụng nó Immer không thêm vào kích thước gói ứng dụng tổng thể. Đó là khoảng 8K phút, 3. 3K phút+gz (tham khảo. ngâm tài liệu. Cài đặt, gói. js. phân tích tổ chức). Tuy nhiên, kích thước gói thư viện đó bắt đầu tự trả tiền bằng cách thu hẹp lượng logic bộ giảm tốc trong ứng dụng của bạn. Ngoài ra, lợi ích của mã dễ đọc hơn và loại bỏ các lỗi đột biến có giá trị lớn Immer cũng thêm một chút chi phí hoạt động trong thời gian chạy. Tuy nhiên, theo trang tài liệu "Hiệu suất" của Immer, chi phí hoạt động không có ý nghĩa trong thực tế. Ngoài ra,. Thay vào đó, chi phí cập nhật giao diện người dùng quan trọng hơn nhiều Vì vậy, mặc dù việc sử dụng Immer không phải là "miễn phí", nhưng chi phí gói và chi phí hoàn hảo đủ nhỏ để xứng đáng Điểm khó khăn thực tế nhất khi sử dụng Immer là trình gỡ lỗi trình duyệt hiển thị Proxies theo cách khó hiểu, điều này khiến khó kiểm tra các biến trạng thái trong khi gỡ lỗi. Đây chắc chắn là một sự khó chịu. Tuy nhiên, điều này không thực sự ảnh hưởng đến hành vi thời gian chạy và chúng tôi đã ở trên trang này. (Do việc sử dụng Proxy ngày càng rộng rãi như một phần của các thư viện như Mobx và Vue 3, điều này cũng không phải là duy nhất đối với Immer. ) Một vấn đề khác là giáo dục và hiểu biết. Redux luôn yêu cầu tính không thay đổi trong bộ giảm tốc và do đó, việc nhìn thấy mã "đột biến" có thể gây nhầm lẫn. Chắc chắn những người dùng Redux mới có thể thấy những "đột biến" đó trong mã ví dụ, cho rằng việc sử dụng Redux là bình thường và sau đó thử làm điều tương tự bên ngoài 0. Điều này thực sự sẽ gây ra các đột biến và lỗi thực sự, bởi vì nó nằm ngoài khả năng của Immer trong việc hoàn thành các bản cập nhậtChúng tôi đã giải quyết vấn đề này bằng cách bao gồm nhiều phần được đánh dấu để nhấn mạnh điều đó và thêm trang tài liệu cụ thể mà bạn hiện đang đọc này Kiến trúc và ý địnhCó thêm hai lý do tại sao Immer không phải là tùy chọn Một là kiến trúc của RTK. 0 và 9 được triển khai bằng cách nhập trực tiếp Immer. Không có cách nào dễ dàng để tạo một phiên bản của một trong số chúng có tùy chọn 2 giả định. Bạn không thể thực hiện nhập tùy chọn và chúng tôi cần có sẵn Immer ngay lập tức và đồng bộ trong lần tải đầu tiên của ứng dụngNgoài ra, RTK hiện gọi ngay khi nhập, để đảm bảo rằng Immer hoạt động chính xác trong môi trường không hỗ trợ Proxy ES6 (chẳng hạn như IE11 và các phiên bản React Native cũ hơn). Điều này là cần thiết vì Immer đã tách hành vi ES5 thành một plugin trong khoảng phiên bản 6. 0, nhưng việc bỏ hỗ trợ ES5 sẽ là một thay đổi đột phá lớn đối với RTK và phá vỡ người dùng của chúng tôi. Bởi vì RTK tự gọi 3 từ điểm vào, nên Immer luôn được kéo vàoVà cuối cùng. Theo mặc định, Immer được tích hợp vào RTK vì chúng tôi tin rằng đó là lựa chọn tốt nhất cho người dùng của chúng tôi. Chúng tôi muốn người dùng của mình sử dụng Immer và coi đó là một thành phần quan trọng không thể thương lượng của RTK. Những lợi ích tuyệt vời như mã giảm tốc đơn giản hơn và ngăn chặn các đột biến ngẫu nhiên vượt xa những mối quan tâm tương đối nhỏ |