2016-03-25 43 views
20

Trong Redux tôi có thể dễ dàng đăng ký để lưu trữ những thay đổi vớiTheo dõi thay đổi tài sản duy nhất trong cửa hàng trong Redux

store.subscribe(() => my handler goes here) 

Nhưng nếu cửa hàng của tôi là đầy đủ của các đối tượng khác nhau và trong một địa điểm cụ thể trong ứng dụng của tôi, tôi muốn đăng ký các thay đổi chỉ được thực hiện trong một đối tượng cụ thể trong cửa hàng?

Trả lời

45

Không có cách nào để đăng ký một phần của cửa hàng khi sử dụng trực tiếp subscribe, nhưng với tư cách là người tạo Redux tự nói - don't use subscribe directly! Để dòng dữ liệu của ứng dụng Redux thực sự hoạt động, bạn sẽ muốn một thành phần kết thúc tốt đẹp toàn bộ ứng dụng. Thành phần này sẽ đăng ký với cửa hàng của bạn. Phần còn lại của các thành phần của bạn sẽ được trẻ em để thành phần này wrapper và sẽ chỉ nhận được các phần của nhà nước mà họ cần.

Nếu bạn đang sử dụng Redux với React thì có tin tốt - gói chính thức react-redux sẽ giải quyết vấn đề này cho bạn! Nó cung cấp thành phần bao bọc đó, được gọi là <Provider />. Sau đó, bạn sẽ có ít nhất một "thành phần thông minh" lắng nghe những thay đổi trạng thái được chuyển xuống bởi Provider từ cửa hàng. Bạn có thể chỉ định phần nào của trạng thái cần nghe và các phần của trạng thái sẽ được chuyển xuống dưới dạng đạo cụ cho thành phần đó (và sau đó tất nhiên, nó có thể chuyển những phần đó xuống cho con riêng của nó). Bạn có thể chỉ định điều đó bằng cách sử dụng chức năng connect() trên thành phần "thông minh" của mình và sử dụng chức năng mapStateToProps làm thông số đầu tiên. Để tóm tắt lại: phần gốc

Quấn với Provider thành phần đặt mua để lưu trữ thay đổi

ReactDOM.render(
    <Provider store={store}> 
    <App /> 
    </Provider>, 
    document.getElementById('root') 
) 

Bây giờ bất kỳ con của <App /> được bao bọc bởi connect() sẽ là một "thông minh" thành phần. Bạn có thể vượt qua trong mapStateToProps để chọn một số phần nhất định của tiểu bang và cung cấp những phần đó làm đạo cụ.

const mapStateToProps = (state) => { 
    return { 
     somethingFromStore: state.somethingFromStore 
    } 
} 

class ChildOfApp extends Component { 
    render() { 
     return <div>{this.props.somethingFromStore}</div> 
    } 
} 

//wrap App in connect and pass in mapStateToProps 
export default connect(mapStateToProps)(ChildOfApp) 

Rõ ràng <App /> có thể có nhiều trẻ em và bạn có thể chọn và chọn phần nào của nhà nước các mapStateToProps nên lắng nghe cho mỗi con của nó. Tôi khuyên bạn nên đọc tài liệu theo số usage with React để hiểu rõ hơn về luồng này.

+3

Cảm ơn bạn đã trả lời chi tiết như vậy –

+0

Thật tuyệt vời. Tôi muốn có một thành phần để phản ứng với một hành động. Giả sử có một thành phần 'NavBar' gửi một hành động' toggleDrawer'. Hành động này lưu trữ một giá trị trong kho đại diện cho trạng thái của ngăn kéo 'isDrawerOpen'. Sau đó, làm thế nào tôi làm cho ngăn kéo được mở ra khi hành động được gửi đi? Ngoài ra ở đây có một xung đột tiềm năng: bản thân ngăn kéo có thể được mở và nó điều khiển thuộc tính 'mở' của nó, vì vậy việc thay đổi' isDrawerOpen' khỏi ngăn kéo sẽ gây ra một vòng lặp vô hạn ... – Miquel

+0

vẫn còn có mã trong 'connect' để trả lời tất cả các thay đổi và thực hiện ít nhất một số mã trước khi so sánh sự trở lại trước đó và tiếp theo của 'mapStateToProps', do đó ảnh hưởng đến hiệu suất không cần thiết. Tôi chỉ tự hỏi nếu chúng ta có thể phát hiện tên của các phím mong muốn, ví dụ: 'function mapStateToProps (({someKey, anotherReducerKey}) => ...' và chỉ đăng ký với những cái đó. Trong javascript bạn có thể lấy tên của các đối số - Câu hỏi đặt ra là bạn có thể lấy tên của các khóa bị phá hủy của các đối số này –

7

Redux chỉ cung cấp một cách chung duy nhất để biết thời điểm cửa hàng đã cập nhật: phương pháp subscribe. Gọi lại tới subscribe không nhận được bất kỳ thông tin nào về những gì có thể đã thay đổi vì API subscribe cố tình ở mức thấp và chỉ cần chạy từng cuộc gọi lại mà không có đối số. Tất cả những gì bạn biết là cửa hàng đã cập nhật theo một cách nào đó.

Do đó, ai đó phải viết logic cụ thể để so sánh trạng thái cũ so với trạng thái mới và xem liệu có bất kỳ điều gì đã thay đổi hay không. Bạn có thể xử lý điều này bằng cách sử dụng React-Redux, chỉ định hàm mapStateToProps cho thành phần của bạn, triển khai componentWillReceiveProps trong thành phần của bạn và kiểm tra xem các đạo cụ cụ thể từ cửa hàng có thay đổi hay không.

Ngoài ra còn có một vài thư viện addon cố xử lý trường hợp này: https://github.com/ashaffer/redux-subscribehttps://github.com/jprichardson/redux-watch. Cả hai về cơ bản cho phép bạn chỉ định một phần cụ thể của tiểu bang để xem xét, sử dụng các cách tiếp cận khác nhau.

0

Ngoài những gì Andy Noelker đã nói, mapStateToProps không chỉ chuyển một phần của tiểu bang xuống đúng cây thành phần của bạn, nó còn đăng ký các thay đổi được thực hiện trực tiếp trong các phần đã đăng ký này của tiểu bang.

Đúng là mọi chức năng mapStateToProp bạn liên kết với cửa hàng sẽ được gọi mỗi lần bất kỳ phần nào của trạng thái được thay đổi, nhưng kết quả cuộc gọi bị cạn so với cuộc gọi trước đó - nếu các khóa cấp cao nhất bạn đã đăng ký không thay đổi (tham chiếu vẫn giữ nguyên). Sau đó mapStateToProps sẽ không gọi lại. Vì vậy, nếu bạn muốn khái niệm này hoạt động, bạn phải giữ mapStateToProps đơn giản, không kết hợp, thay đổi kiểu hoặc bất cứ thứ gì, chúng chỉ đơn giản là truyền xuống các phần của trạng thái.

Nếu bạn muốn giảm dữ liệu từ trạng thái khi đăng ký, ví dụ bạn có dữ liệu danh sách trong tiểu bang và bạn muốn chuyển đổi nó thành đối tượng có id là khóa hoặc bạn muốn kết hợp nhiều tiểu bang vào cấu trúc dữ liệu, bạn nên kết hợp mapStateToProps với createSelector từ thư viện reselect, bằng cách thực hiện tất cả các sửa đổi này bên trong bộ chọn. Các bộ chọn là các hàm thuần túy làm giảm và các khối trạng thái cache được truyền vào như đầu vào và nếu đầu vào không thay đổi - chúng trả lại chính xác cùng một tham chiếu mà chúng đã thực hiện trong lần gọi cuối - mà không thực hiện việc giảm.

0

Tôi nên theo dõi chủ đề này để nhận thông tin vì tôi cần nó.

Cho đến nay tôi nghĩ: trạng thái hiện tại & trạng thái trước đó có thể được sử dụng như là đối tượng 2 json. So sánh sự khác biệt giữa hai JSON có thể giúp chúng tôi tìm ra sự thay đổi thực sự.

Chúng ta có thể tạo một hàm để chuyển tên thuộc tính của trạng thái, sau đó chúng ta có thể so sánh hai đối tượng json nhỏ hơn, dễ dàng hơn và ngắn hơn.

Các vấn đề liên quan