componentDidMount tương đương với một hàm React / thành phần Hooks?


99

Có những cách nào để mô phỏng componentDidMountcác thành phần chức năng trong React thông qua hook?

Câu trả lời:


199

Đối với phiên bản hooks ổn định (Phiên bản React 16.8.0+)

Đối với componentDidMount

useEffect(() => {
  // Your code here
}, []);

Đối với componentDidUpdate

useEffect(() => {
  // Your code here
}, [yourDependency]);

Đối với componentWillUnmount

useEffect(() => {
  // componentWillUnmount
  return () => {
     // Your code here
  }
}, [yourDependency]);

Vì vậy, trong tình huống này, bạn cần chuyển sự phụ thuộc của mình vào mảng này. Giả sử bạn có một trạng thái như thế này

const [count, setCount] = useState(0);

Và bất cứ khi nào số lượng tăng lên, bạn muốn kết xuất lại thành phần hàm của mình. Sau đó, bạn useEffectsẽ trông như thế này

useEffect(() => {
  // <div>{count}</div>
}, [count]);

Bằng cách này bất cứ khi nào số lượng của bạn cập nhật, thành phần của bạn sẽ hiển thị lại. Hy vọng rằng điều này sẽ giúp một chút.


Giải thích cặn kẽ! Có cách nào để mô phỏng componentDidReceiveProps không?
jeyko

1
Tôi không biết về nó ngay cả khi nó tồn tại. Bạn có thể kiểm tra chuỗi này cho nó tho github.com/facebook/react/issues/3279
Mertcan Diken

1
Cảm ơn bạn vì điều này vì tôi không biết về lập luận thứ hai trong useState. Đối với bất kỳ ai đang đọc điều này, xin lưu ý rằng việc để lại đối số thứ hai undefinedsẽ khiến hiệu ứng của bạn được kích hoạt trên mọi kết xuất (nếu tôi không nhầm).
dimiguel

Bạn có nghĩa là phụ thuộc của useEffect (truyền một mảng phụ thuộc)? Nếu vậy, nếu bạn để trống, đó là một lỗi trong mã. Đối với giải cấu trúc mảng, bạn cần cả [count, setCount] vì count là biến trạng thái của bạn trong ví dụ này và setCount là hàm của bạn để cập nhật trạng thái đó.
Mertcan Diken

Cảm ơn vì câu trả lời. Tài liệu về điều này ở đây reactjs.org/docs/hooks-effect.html
Josh

3

Mặc dù câu trả lời được chấp nhận hoạt động, nó không được khuyến khích. Khi bạn có nhiều hơn một trạng thái và bạn sử dụng nó với useEffect, nó sẽ đưa ra cảnh báo về việc thêm nó vào mảng phụ thuộc hoặc hoàn toàn không sử dụng nó.

Đôi khi nó gây ra sự cố có thể cung cấp cho bạn kết quả không thể đoán trước. Vì vậy, tôi khuyên bạn nên dành một chút nỗ lực để viết lại hàm của mình dưới dạng lớp. Có rất ít thay đổi và bạn có thể có một số thành phần dưới dạng lớp và một số thành phần dưới dạng hàm. Bạn không bắt buộc chỉ sử dụng một quy ước.

Lấy ví dụ này

function App() {
  const [appointments, setAppointments] = useState([]);
  const [aptId, setAptId] = useState(1);

  useEffect(() => {
    fetch('./data.json')
      .then(response => response.json())
      .then(result => {
        const apts = result.map(item => {
          item.aptId = aptId;
          console.log(aptId);
          setAptId(aptId + 1);
          return item;
        })
        setAppointments(apts);
      });
  }, []);

  return(...);
}

class App extends Component {
  constructor() {
    super();
    this.state = {
      appointments: [],
      aptId: 1,
    }
  }

  componentDidMount() {
    fetch('./data.json')
      .then(response => response.json())
      .then(result => {
        const apts = result.map(item => {
          item.aptId = this.state.aptId;
          this.setState({aptId: this.state.aptId + 1});
          console.log(this.state.aptId);
          return item;
        });
        this.setState({appointments: apts});
      });
  }

  render(...);
}

Đây chỉ là ví dụ . vì vậy chúng ta đừng nói về các phương pháp hay nhất hoặc các vấn đề tiềm ẩn với mã. Cả hai điều này đều có cùng một logic nhưng sau này chỉ hoạt động như mong đợi. Bạn có thể nhận được chức năng componentDidMount với useEffect đang chạy trong thời gian này, nhưng khi ứng dụng của bạn phát triển, có khả năng bạn CÓ THỂ gặp một số vấn đề. Vì vậy, thay vì viết lại ở giai đoạn đó, tốt hơn nên làm điều này ở giai đoạn đầu.

Bên cạnh đó, OOP cũng không đến nỗi tệ, nếu Lập trình hướng thủ tục là đủ, chúng ta đã không bao giờ có Lập trình hướng đối tượng. Đôi khi điều đó gây đau đớn, nhưng tốt hơn (về mặt kỹ thuật. Các vấn đề cá nhân sang một bên).


1
Tôi đã làm điều này. Tôi phải đối mặt với vấn đề sử dụng móc. Vấn đề đã biến mất sau khi chuyển đổi nó thành lớp.
Julez

2

Không có componentDidMountcác thành phần chức năng, nhưng React Hooks cung cấp một cách bạn có thể mô phỏng hành vi bằng cách sử dụng useEffecthook.

Truyền một mảng trống làm đối số thứ hai useEffect()để chỉ chạy lệnh gọi lại trên mount.

Vui lòng đọc tài liệu trênuseEffect .

function ComponentDidMount() {
  const [count, setCount] = React.useState(0);
  React.useEffect(() => {
    console.log('componentDidMount');
  }, []);

  return (
    <div>
      <p>componentDidMount: {count} times</p>
      <button
        onClick={() => {
          setCount(count + 1);
        }}
      >
        Click Me
      </button>
    </div>
  );
}

ReactDOM.render(
  <div>
    <ComponentDidMount />
  </div>,
  document.querySelector("#app")
);
<script src="https://unpkg.com/react@16.7.0-alpha.0/umd/react.development.js"></script>
<script src="https://unpkg.com/react-dom@16.7.0-alpha.0/umd/react-dom.development.js"></script>

<div id="app"></div>


0

Bạn muốn sử dụng useEffect(), tùy thuộc vào cách bạn sử dụng hàm, có thể hoạt động giống như componentDidMount ().

Ví dụ. bạn có thể sử dụng loadedthuộc tính trạng thái tùy chỉnh ban đầu được đặt thành false và chuyển nó thành true khi kết xuất và chỉ kích hoạt hiệu ứng khi giá trị này thay đổi.

Tài liệu


1
Giải pháp này không phải là lý tưởng. Bạn không nên sử dụng một giá trị trạng thái chỉ để xác định xem thành phần đã được gắn kết hay chưa. Ngoài ra, nếu bạn đang sử dụng một thuộc tính, một bản tham chiếu sẽ tốt hơn vì nó sẽ không kích hoạt một lần hiển thị lại khác.
Yangshun Tay

0

hook tương đương chính xác cho componentDidMount () là

useEffect(()=>{},[]);

hy vọng điều này hữu ích :)

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.