React.useState không tải lại trạng thái từ các đạo cụ


96

Tôi đang mong đợi trạng thái tải lại khi thay đổi đạo cụ, nhưng điều này không hoạt động và userbiến không được cập nhật trong lần useStategọi tiếp theo , có chuyện gì vậy?

function Avatar(props) {
  const [user, setUser] = React.useState({...props.user});
  return user.avatar ? 
         (<img src={user.avatar}/>)
        : (<p>Loading...</p>);
}

codepen

Câu trả lời:


216

Đối số được truyền cho useState là trạng thái ban đầu giống như thiết lập trạng thái trong hàm khởi tạo cho một thành phần lớp và không được sử dụng để cập nhật trạng thái khi re-render

Nếu bạn muốn cập nhật trạng thái khi thay đổi trụ, hãy sử dụng useEffecthook

function Avatar(props) {
  const [user, setUser] = React.useState({...props.user});

  React.useEffect(() => {
      setUser(props.user);
  }, [props.user])

  return user.avatar ? 
         (<img src={user.avatar}/>)
        : (<p>Loading...</p>);
}

Bản demo làm việc


18
Khi thiết lập trạng thái ban đầu trong phương thức khởi tạo, nó rõ ràng để hiểu rằng phương thức khởi tạo đó được gọi một lần khi tạo cá thể lớp. Với hooks, có vẻ như useState được gọi mỗi lần gọi hàm và mỗi lần nó sẽ khởi tạo trạng thái, nhưng một số "phép thuật" không giải thích được xảy ra ở đó.
importantyster 25/02/19

Có thể bài đăng này làm sáng tỏ về nó stackoverflow.com/questions/54673188/…
Shubham Khatri,

nếu bạn cần đạo cụ hợp nhất vào trạng thái, bạn gặp khó khăn trong một vòng lặp vô hạn khi sử dụng tạo-phản ứng ứng dụng đòi hỏi nhà nước phải trong mảng phụ thuộc
user210757

2
Điều này kết thúc việc thiết lập trạng thái ban đầu hai lần, khá khó chịu. Tôi tự hỏi liệu bạn có thể đặt trạng thái ban đầu thành null và sau đó sử dụng React.useEffectđể đặt trạng thái ban đầu tại mỗi thời điểm không.
CMCDragonkai

2
Điều này không hoạt động nếu trạng thái cũng đang kiểm soát kết xuất. Tôi có một thành phần chức năng hiển thị dựa trên đạo cụ và kết xuất dựa trên trạng thái. Nếu trạng thái yêu cầu thành phần hiển thị vì nó đã thay đổi, thì useEffect sẽ chạy và đặt trạng thái trở lại giá trị mặc định. Đây thực sự là một thiết kế tồi về phía họ.
Greg Veres

1

Các thành phần chức năng nơi chúng tôi sử dụng useStateđể đặt giá trị ban đầu cho biến của chúng tôi, nếu chúng tôi chuyển giá trị ban đầu qua các props, nó sẽ luôn đặt cùng giá trị ban đầu cho đến khi bạn không sử dụng useEffecthook,

ví dụ trường hợp của bạn, điều này sẽ làm công việc của bạn

 React.useEffect(() => {
      setUser(props.user);
  }, [props.user])

Hàm được truyền cho useEffect sẽ chạy sau khi kết xuất được cam kết với màn hình.

Theo mặc định, các hiệu ứng chạy sau mỗi lần hiển thị hoàn tất, nhưng bạn có thể chọn chỉ kích hoạt chúng khi một số giá trị nhất định đã thay đổi.

React.useEffect(FunctionYouWantToRunAfterEveryRender)

nếu bạn chỉ truyền một đối số để useEffect, nó sẽ chạy phương thức này sau mỗi lần hiển thị, bạn có thể quyết định thời điểm kích hoạt điều này FunctionYouWantToRunAfterEveryRenderbằng cách truyền đối số thứ hai cho useEffect

React.useEffect(FunctionYouWantToRunAfterEveryRender, [props.user])

như bạn nhận thấy, tôi đang chuyển [props.user] bây giờ useEffectsẽ chỉ kích FunctionYouWantToRunAfterEveryRenderhoạt chức năng này khi props.userđược thay đổi

tôi hy vọng điều này sẽ giúp ích cho sự hiểu biết của bạn, hãy cho tôi biết nếu cần có bất kỳ cải tiến nào, cảm ơn


0

Tham số được truyền đến React.useState()chỉ là giá trị ban đầu cho trạng thái đó. React sẽ không nhận ra đó là thay đổi trạng thái, chỉ thiết lập giá trị mặc định của nó. Ban đầu bạn sẽ muốn đặt trạng thái mặc định, sau đó gọi có điều kiện, trạng thái setUser(newValue)này sẽ được công nhận là trạng thái mới và hiển thị lại thành phần.

Tôi khuyên bạn nên thận trọng khi cập nhật trạng thái mà không có một số điều kiện để giữ cho nó không được cập nhật liên tục và do đó kết xuất lại mỗi khi nhận được đạo cụ. Bạn có thể muốn xem xét việc nâng chức năng trạng thái cho một thành phần mẹ và chuyển trạng thái của thành phần mẹ xuống Hình đại diện này như một chỗ dựa.


-2

Theo tài liệu ReactJS về Hooks :

Nhưng điều gì sẽ xảy ra nếu ứng dụng hỗ trợ bạn bè thay đổi trong khi thành phần đó ở trên màn hình? Thành phần của chúng tôi sẽ tiếp tục hiển thị trạng thái trực tuyến của một người bạn khác. Đây là một lỗi. Chúng tôi cũng sẽ gây rò rỉ bộ nhớ hoặc sự cố khi ngắt kết nối vì cuộc gọi hủy đăng ký sẽ sử dụng sai ID bạn bè.

Tương tác duy nhất của bạn ở đây sẽ xảy ra khi thay đổi đạo cụ, điều này dường như không hoạt động. Bạn có thể (vẫn theo tài liệu) sử dụng componentDidUpdate (prevProps) để chủ động bắt bất kỳ bản cập nhật nào cho đạo cụ.

Tái bút: Tôi không có đủ mã để đánh giá, nhưng bạn không thể chủ động đặtUser () bên trong chức năng Avatar (đạo cụ) của mình?


-12

Trong thế giới phản ứng, bạn nên cập nhật trạng thái của mình trong hàm componentWillRecieveProps (nextProps), trong những trường hợp như vậy.


4
Đó là không còn đúng đối với các phiên bản mới nhất của phản ứng
Shubham Khatri
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.