2015-11-06 21 views
9

Tôi có bộ định tuyến đơn giản (bắt đầu bằng redux-router và chuyển sang react-router để loại bỏ biến).MapStateToProps của React-redux connect() được gọi nhiều lần trên điều hướng bộ định tuyến phản ứng

<Router history={history}> 
    <Route component={Admin} path='/admin'> 
    <Route component={Pages} path='pages'/> 
    <Route component={Posts} path='posts'/> 
    </Route> 
</Router> 

Thành phần quản trị về cơ bản chỉ là {this.props.children} với một số điều hướng; nó không phải là thành phần ed connect.

Trang thành phần là một thành phần connect ed với mapStateToProps() như vậy:

function mapStateToProps (state) { 
    return { 
    pages: state.entities.pages 
    }; 
} 

bài viết thậm chí còn thú vị hơn:

function mapStateToProps (state) { 
    let posts = map(state.entities.posts, post => { 
    return { 
     ...post, 
     author: findWhere(state.entities.users, {_id: post.author}) 
    }; 
    } 

    return { 
    posts 
    }; 
} 

Và sau đó khi tôi tải trang hoặc chuyển qua lại giữa bài/trang các tuyến đường Tôi nhận được sau đây trong console.log của tôi().

// react-router navigate to /posts 

Admin render() 
posts: map state to props 
Posts render() 
posts: map state to props 
Posts render() 
posts: map state to props 

// react-router navigate to /pages 

Admin render() 
pages: map state to props 
Pages render() 
pages: map state to props 

Vì vậy, câu hỏi của tôi là: tại sao mapStateToProps được gọi nhiều lần vào những thay đổi tuyến đường?

Ngoài ra, tại sao hàm map đơn giản trong mapStateToProps làm cho nó được gọi là lần thứ ba trong vùng chứa Bài đăng?

Tôi đang sử dụng các phần tử cơ bản loggercrashReporter từ các tài liệu Redux và nó không báo cáo bất kỳ thay đổi trạng thái hoặc sự cố nào. Nếu trạng thái không thay đổi tại sao các thành phần lại hiển thị nhiều lần?

+1

Mọi thông tin cập nhật về điều này, có khả năng không? –

+0

Thành thật mà nói, không. Tôi bắt đầu xóa những thứ khác nhau để xem điều gì có thể kích hoạt nó. Tôi chỉ nhìn vào nó một lần nữa và có vẻ như hành động '@@ INIT' của Redux kích hoạt nó thêm một lần nữa, nhưng rất khó để ghi lại hành động đó. Khi kết xuất trên máy chủ, nó chỉ ghi một 'mapStateToProps' duy nhất cho mỗi vùng chứa.Đã hy vọng cho một câu trả lời từ @DanAbramov – Mike

+0

Tôi cũng đã xem xét ví dụ thế giới thực của Redux để xem bao nhiêu lần mapStateToProps đang được gọi ở đó và nó chứa rất nhiều cuộc gọi. Tôi nghĩ rằng nó không phải là khá quan trọng miễn là bạn sử dụng một công cụ như [Chọn lại] (https://github.com/rackt/reselect) để ghi nhớ bộ chọn của bạn. – Mike

Trả lời

0

Reselect cho phép bạn tạo các hàm seloized selector cho xử lý trạng thái có nguồn gốc.

Redux's documentation giải thích bằng ví dụ về cách sử dụng. Readme của repo cũng có một ví dụ nhanh.

+1

Tôi đã giải quyết điều này từ lâu, nhưng sẽ chấp nhận câu trả lời này vì chọn lại là một lib tuyệt vời. – Mike

8

Trải nghiệm với react-redux, bạn không nên xử lý thuộc tính cửa hàng bên trong mapStateToPropsconnect uses shallow checking of bound store attributes to check for diff.

Để kiểm tra xem thành phần của bạn có cần được cập nhật hay không, react-redux gọi mapStateToProps và kiểm tra thuộc tính cấp đầu tiên của kết quả. Nếu một trong số họ thay đổi (=== kiểm tra bình đẳng), thành phần sẽ cập nhật với các đạo cụ mới. Trong trường hợp của bạn posts thay đổi (map chuyển đổi) mỗi khi mapStateToProps được gọi, vì vậy thành phần của bạn được cập nhật trên mọi thay đổi của cửa hàng!

giải pháp của bạn sẽ trở lại chỉ tham khảo trực tiếp các thuộc tính của cửa hàng của bạn:

function mapStateToProps (state) { 
    return { 
    posts: state.entities.posts, 
    users: state.entities.users 
    }; 
} 

Sau đó, trong thành phần của bạn, bạn có thể định nghĩa một hàm xử lý dữ liệu của bạn theo yêu cầu:

getPostsWithAuthor() { 
    const { posts, users } = this.props; 

    return map(posts, post => { 
    return { 
     ...post, 
     author: findWhere(users, {_id: post.author}) 
    }; 
    }); 
} 
+0

có vẻ như liên kết github của bạn đã chết .... bạn đang đề cập đến dòng này? https://github.com/reactjs/react-redux/blob/db91ed900107e58c15000e2a45c29e85c63ca2eb/src/connect/connect.js#L36 – sfletche

+0

Thật vậy, mã của 'connect.js' đã di chuyển và thay đổi rất nhiều, cảm ơn bạn @sfletche cho thông báo! Lưu ý rằng 'connect' dường như chấp nhận các điều kiện cập nhật tùy chỉnh ngay bây giờ, vì vậy OP có thể thực sự tinh chỉnh chúng một cách cụ thể (mặc dù tôi khuyên bạn không nên chuyển đổi bất kỳ điều gì trong' mapStateToProps' nhưng tại thời điểm cuối cùng bên trong thành phần) – blint

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