2015-12-18 23 views
27

Tôi có thành phần React gửi một thay đổi trạng thái redux trong hàm componentWillMount của nó. Lý do là khi thành phần được tải, nó cần lấy số id từ url (được hỗ trợ bởi react-router) và kích hoạt một hành động thiết lập trạng thái với dữ liệu của id đó.Ngăn thành phần phản ứng khỏi hiển thị hai lần khi sử dụng redux với componentWillMount

Dưới đây là các thành phần:

class Editor extends React.Component { 

    componentWillMount() { 
     const { dispatch, params } = this.props 
     dispatch(editItem(params.id)) 
    } 

    render() { 
     const item = this.props.item 
     console.log("Editing", item) 
    } 
} 

export default connect(state => ({item: state.item}))(Editor) 

Dưới đây là đánh bắt: render là nhận được gọi là hai lần. item không được xác định trên cuộc gọi đầu tiên và hợp lệ vào lần thứ hai. Lý tưởng nhất, nó chỉ nên được gọi khi this.props.item thực sự tồn tại (sau khi hành động editItem đã được gửi đi và chạy).

Theo số React docs: "Nếu bạn gọi setState trong phương thức này, render() sẽ thấy trạng thái được cập nhật và sẽ chỉ được thực hiện một lần bất kể thay đổi trạng thái".

Trong Redux, dispatch tương đương với việc gọi setState, vì nó dẫn đến thay đổi trạng thái. Tuy nhiên, tôi đoán một cái gì đó trong cách hoạt động connect vẫn gây ra render được gọi hai lần.

Có cách nào khác ngoài việc thêm một dòng như if (!item) return; không?

Trả lời

0

editItem làm gì? Nó có thêm mục vào trạng thái redux hay không?

Nếu nó đang thêm tôi tưởng tượng những gì đang xảy ra là một chu kỳ render xảy ra với các đạo cụ hiện tại, tức là mục đang trống. Sau đó, nó được trả lại khi đạo cụ đã thay đổi, thông qua thiết lập mục.

Một cách tiếp cận để sửa loại sắp xếp này là tạo thành phần thứ tự cao hơn bao bọc Editor và gọi hành động gửi, hiển thị được đặt thành màn hình tải hoặc div trống cho đến khi mục được đặt. Bằng cách đó bạn có thể yên tâm rằng Editor sẽ có một mục.

Nhưng không biết editItem làm gì thì khó mà biết được. Có lẽ bạn có thể dán mã cho điều đó?

6

Một điều bạn có thể làm là tạo thành phần thứ tự cao hơn xử lý mẫu cơ bản tải thành phần khác (hoặc không có thành phần) trước khi các đạo cụ bắt buộc được tải.

export const LoaderWrapper = function(hasLoaded, Component, LoaderComponent, onLoad) { 
    return props => { 
     if (hasLoaded(props)) { 
      return <Component {...props} /> 
     } 
     else { 
      if (onLoad) onLoad(props) 

      return { LoaderComponent ? <LoaderComponent /> : null } 
     } 
    } 
} 

Sau đó, bạn có thể bọc thành phần của mình trước khi kết nối để có được hành vi mong muốn.

export default connect(state => ({item: state.item}))(LoaderWrapper(
    ((props) => !!props.item), 
    Editor, 
    null, 
    (props) => props.dispatch(editItem(props.params.id)) 
)) 

Bạn có thể muốn thêm một số phép thuật cắt để đảm bảo bạn có thể soạn các loại chức năng trình bao này độc đáo hơn. Hãy xem recompose để biết thêm thông tin.

+0

'return LoaderComponent? : null' – incleaf

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