2014-07-22 25 views
29

Tôi khá mới với react.js và đang trong quá trình thử nghiệm bằng cách xây dựng bố cục kiểu nề.React.js: ghi đè setState, không hợp nhất

Tôi hiển thị từng phần tử cho DOM, sau đó tôi cần lặp qua từng mục và áp dụng vị trí x và y dựa trên các phần tử trước đó.

Mô hình ban đầu trông như thế này:

[ 
    { 
    "title": "The Forrest", 
    "description": "some cool text", 
    "imgSmallSrc": "/img/img4-small.jpg", 
    "imgAlt": "Placeholder image", 
    "tags": [ 
     "Design", 
     "Mobile", 
     "Responsive" 
    ], 
    "date": 1367154709885, 
    "podStyle": { 
     "width": 253 
    } 
    } 
] 

(Tôi đã chỉ được hiển thị một mục để giữ cho mọi thứ ngắn).

Khi tôi hoàn thành vòng lặp và có dữ liệu x và y của mình, tôi muốn áp dụng điều này cho đối tượng podStyle. Tôi gọi setState với các dữ liệu sau:

[ 
    { 
    "podStyle": { 
     "x": 0, 
     "y": 0, 
     "height": 146, 
     "width": 253 
    } 
    } 
] 

Điều này dường như xóa tất cả dữ liệu hiện tại khỏi mô hình và để lại cho tôi dữ liệu podStyle. Tôi có hiểu lầm cách hợp nhất này hoạt động không?

Cảm ơn bạn đã giúp đỡ!

+3

Hãy thử [người trợ giúp bất biến] (https: //facebook.githu b.io/react/docs/update.html) trong phần bổ sung của React cho một cách khai báo sửa đổi các đối tượng trạng thái phức tạp. –

Trả lời

54

Nếu trạng thái của bạn là một đối tượng:

getInitialState: function() { 
    return { x: 0, y: 0 }; 
} 

bạn có thể sử dụng setState để thiết lập phím cá nhân trên đối tượng đó:

this.setState({ x: 1 }); // y still == 0 

Phản ứng thực hiện không kết hợp thông minh của tiểu bang; ví dụ, điều này không làm việc:

getInitialState: function() { 
    return { 
    point: { x: 0, y: 0 }, 
    radius: 10 
    }; 
} 

this.setState({point: {x: 1}}); 
// state is now == {point: {x: 1}, radius: 10} (point.y is gone) 

[Chỉnh sửa]

Như đã đề cập bởi @ssorallen, bạn có thể sử dụng the immutability helpers để có được hiệu quả bạn đang sau:

var newState = React.addons.update(this.state, { 
    point: { x: {$set: 10} } 
}); 
this.setState(newState); 

Xem this JSFiddle ví dụ: http://jsfiddle.net/BinaryMuse/HW6w5/

+0

Vì vậy, tôi khá chắc chắn rằng tôi đang thiết lập nhà nước theo ví dụ thứ hai của bạn, tuy nhiên, 'bán kính' trong trường hợp này là nhận được gỡ bỏ. Khi tôi về nhà tối nay tôi sẽ có một cuộc chơi xung quanh và chắc chắn rằng tôi đang thiết lập một cách chính xác. Cảm ơn sự giúp đỡ của bạn Brandon! – DanV

+1

@DanV Dưới đây là một JSFiddle để chứng minh mã trong câu trả lời của tôi. http://jsfiddle.net/BinaryMuse/HW6w5/ Tôi cũng đã thêm một nút để sử dụng những người giúp đỡ bất biến được đề cập bởi ssorallen, mà những gì bạn muốn làm. –

+0

Cảm ơn bạn rất nhiều vì đã giúp Brandon. Điều này chắc chắn đã gửi cho tôi đúng hướng. Tôi đã kết thúc bằng cách sử dụng helper hợp nhất $ như mô hình của tôi là hơi khác nhau và tôi cũng đã áp dụng các bản cập nhật cho một số mặt hàng trẻ em. Hoạt động tốt đẹp mặc dù. – DanV

3

Giống như:

getInitialState: function() { 
    return { 
     something: { x: 0, y: 0 }, 
     blah: 10 
    }; 
} 

var state = Object.assign(this.state, { 
    something: Object.assign(this.state.something, { y: 50 }), 
}); 

this.setState(state); 

Sẽ là tốt hơn nếu nó là đệ quy/sâu hơn là cứng mã hóa cây, nhưng tôi sẽ để lại rằng lên đến người đọc :)

+0

'Object.assign' bên ngoài không thực sự làm bất cứ điều gì vì thuộc tính' something' mà bạn gán vẫn đề cập đến đối tượng gốc (mặc dù bị biến đổi). Ngoài ra, bạn không nên biến đổi trực tiếp đối tượng trong tiểu bang. Nó có thể được OK vì bạn gọi 'setState' anyway, nhưng nó không sạch sẽ. Hơn nữa, bạn có thể cung cấp các bản cập nhật một phần cho 'setState' thay vì một đối tượng trạng thái đầy đủ. – herman

+3

Suy nghĩ về nó nhiều hơn một chút: chắc chắn KHÔNG ĐƯỢC thay đổi 'this.state' và sau đó gọi' setState' với tham chiếu đến 'this.state'. Điều này là bởi vì nó sẽ phá vỡ mã trong 'shouldComponentUpdate' có thể so sánh trạng thái tiếp theo với trạng thái trước đó (mà sẽ luôn luôn bằng nhau trong trường hợp này vì cả hai đều là tham chiếu đến cùng một đối tượng). – herman

10

Sự kết hợp là nông cạn, vì vậy this.setState({point}) lá (ed: này. state.radius) nguyên vẹn, nhưng hoàn toàn thay thế (ed: this.state.point).

https://facebook.github.io/react/docs/state-and-lifecycle.html#state-updates-are-merged

Để cung cấp một ES7 + quan điểm về các câu trả lời đã được đưa ra, sử dụng transform-object-rest-spread thay vì Object.assign():

class MyComponent extends React.Component { 
    state = { 
     point: { 
      x: 0, 
      y: 0, 
     }, 
     radius: 10, 
    } 

    handleChange =() => { 
     this.setState({ 
      point: { 
       // rest operator (...) expands out to: 
       ...this.state.point, // x:0, y:0, 
       y: 1, // overwrites old y 
      }, 
      // radius is not overwritten by setState 
     }); 
    } 

    render() { 
     // omitted 
    } 
} 

.babelrc (cũng đòi hỏi transform-class-properties từ babel giai đoạn cài sẵn 2)

{ 
    "presets": ["es2015", "stage-2", "react"], 
    "plugins": ["transform-object-rest-spread"], 
} 
+0

Cảm ơn bạn! Tôi nghĩ đó là một giải pháp tuyệt vời. –

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