cách ưa thích để thay đổi trạng thái React là gì?


97

Giả sử tôi có một danh sách các đối tượng thuần túy this.state.listmà tôi có thể sử dụng để hiển thị danh sách các đối tượng con. Vậy thì cách thích hợp để chèn đối tượng vào là this.state.listgì?

Dưới đây là cách duy nhất tôi nghĩ rằng nó sẽ hoạt động vì bạn không thể thay đổi this.statetrực tiếp như đã đề cập trong tài liệu.

this._list.push(newObject):
this.setState({list: this._list});

Điều này có vẻ xấu với tôi. Có cách nào tốt hơn?


bản sao có thể xảy ra Sửa đổi chính xác các mảng trạng thái trong ReactJS , yêu cầu hợp nhất
Brigand

Tất cả những câu trả lời đó là về việc thêm một phần tử vào một mảng. Nhưng những gì về việc xóa một phần tử khỏi nó? Hay chỉ đơn giản là đặt lại hoàn toàn mảng thành một mảng mới?
Augustin Riedinger

Câu trả lời:


165

concat trả về một mảng mới, vì vậy bạn có thể làm

this.setState({list: this.state.list.concat([newObject])});

một giải pháp thay thế khác là trình trợ giúp bất biến của React

  var newState = React.addons.update(this.state, {
      list : {
        $push : [newObject]
      }
  });

  this.setState(newState);

6
concatlấy một mảng, vì vậy bạn sẽ muốn this.state.list.concat([newObject]).
Sophie Alpert,

@BenAlpert hoạt động cho tôi trong Chrome, bạn có nói đây là hành vi không chuẩn không?
Heap

6
@Heap Chà, nếu bạn truyền một mảng không phải mảng vào concatthì nó sẽ bao bọc nó trong một mảng, nhưng tốt hơn là bạn nên tự thêm mảng để rõ ràng: nếu bạn có [[1,2], [3,4]]và muốn thêm [5,6]làm phần tử tiếp theo, bạn cần phải làm gì .concat([[5,6]])khác sẽ kết thúc với [[1,2], [3,4], 5, 6].
Sophie Alpert,

2
Tôi đánh giá cao ý tưởng đằng sau các trình trợ giúp bất biến (và tôi có thể sẽ sử dụng nó), Array.concatchắc chắn sẽ đánh bại việc thêm một thư viện khác.
Shawn Erquhart

1
Gọi this.setState với một giá trị bắt nguồn từ this.state sẽ khiến bạn gặp phải vấn đề cập nhật loạt. Xem stackoverflow.com/a/41445812/1998186 liên kết đến jsfiddle hiển thị sự cố bạn sẽ gặp phải.
NealeU

40

setState () có thể được gọi với một hàm dưới dạng tham số:

this.setState((state) => ({ list: state.list.concat(newObj) }))

hoặc trong ES5:

this.setState(function(state) {
  return {
   list: state.list.concat(newObj)
  }
})

2
@Arian: React sẽ thực hiện các hướng dẫn đột biến DOM bắt buộc cần thiết để chỉ hiển thị các phần tử mới được thêm vào. Tất nhiên, do bạn mới thêm các phần tử không thay đổi cách các phần tử trước đó hiển thị.
Jose Browne

1
Đây là một câu trả lời tuyệt vời và cảm thấy rõ ràng hơn nhiều so với việc nối mảng chỉ để thực hiện một cú hích, mặc dù đó là ý kiến ​​của tôi.
Matt Styles

2
@Nyalab, bạn có nên đặt phần thân hàm trong dấu ngoặc đơn không? Như hiện tại trong ví dụ của bạn, dấu ngoặc nhọn sau mũi tên béo sẽ bắt đầu một khối, không phải một đối tượng. Một cái gì đó như thế này:this.setState((state) => ({ list: state.list.push(newObj) }))
kumarharsh

3
Mã này hoạt động như thế nào? việc đẩy mạnh phương pháp sẽ trở lại một NUMBER, mà sẽ được đặt trên listbiến
kumarharsh

1
Bạn cũng có thể sử dụng biểu tượng báo:this.setState((state) => ({ list: [...state.list, newObj] }))
amoebe


Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.