componentDidMount еквівалент на функції React / компонент Hooks?


99

Чи існують способи моделювання componentDidMountфункціональних компонентів React за допомогою гачків?

Відповіді:


199

Для стабільної версії хуків (React версії 16.8.0+)

Для componentDidMount

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

Для componentDidUpdate

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

Для componentWillUnmount

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

Отже, у цій ситуації вам потрібно передати свою залежність у цей масив. Припустимо, у вас такий стан

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

І щоразу, коли кількість збільшується, ви хочете повторно відтворити свій функціональний компонент. Тоді ваш useEffectповинен виглядати так

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

Таким чином, щоразу, коли ваш підрахунок оновлень, ваш компонент буде рендерінг. Сподіваємось, це трохи допоможе.


Грунтовне пояснення! Чи є спосіб імітувати componentDidReceiveProps?
jeyko

1
Я цього не знаю, навіть якщо воно існує. Ви можете перевірити цю тему на github.com/facebook/react/issues/3279
Mertcan Diken

1
Дякую за це, оскільки я не знав про другий аргумент у useState. Будь-хто, хто читає це, майте на увазі, що залишення другого аргументу undefinedпризведе до того, що ваш ефект спрацює на кожному рендері (якщо я не помиляюся).
Dimiguel

Ви маєте на увазі залежності useEffect (передача масиву залежностей)? Якщо так, так, якщо залишити це поле порожнім, це помилка в коді. Для деконструкції масиву вам потрібні обидва [count, setCount], оскільки count - це ваша змінна стану в цьому прикладі, а setCount - ваша функція для оновлення цього стану.
Mertcan Diken

Дякую за відповідь. Документація про це тут: reakjs.org/docs/hooks-effect.html
Джош,

3

Хоча прийнята відповідь працює, вона не рекомендується. Коли у вас є більше одного стану, і ви використовуєте його з useEffect, він видасть вам попередження про додавання його до масиву залежностей або взагалі його використання.

Це іноді спричиняє проблему, яка може дати вам непередбачуваний результат. Тому я пропоную вам докласти трохи зусиль, щоб переписати свою функцію як клас. Змінів дуже мало, і ви можете мати деякі компоненти як клас, а деякі як функції. Ви не зобов’язані користуватися лише однією умовою.

Візьмемо це для прикладу

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(...);
}

Це лише для прикладу . тому не можна говорити про найкращі практики чи потенційні проблеми з кодом. І те, і інше має однакову логіку, але пізніше працює лише за очікуванням. Ви можете отримати функціонал componentDidMount із запущеним useEffect на цей час, але в міру зростання вашого додатка є ймовірність того, що ви МОЖЕТЕ зіткнутися з деякими проблемами. Отже, замість того, щоб переписувати на цьому етапі, краще робити це на ранній стадії.

До того ж ООП не настільки поганий, якби було достатньо процедурно-орієнтованого програмування, ми ніколи не мали б об’єктно-орієнтованого програмування. Іноді це боляче, але краще (технічно. Особисті питання в сторону).


1
Я зробив це. Я зіткнувся з проблемою використання гачків. Випуск зник після перетворення його на клас.
Жулез

2

Там немає componentDidMountна функціональних компонентах, але Реагувати Гачки забезпечують спосіб , яким Ви можете емулювати поведінка за допомогою useEffectгачка.

Передайте порожній масив як другий аргумент, useEffect()щоб запустити лише зворотний виклик лише під час монтування.

Будь ласка, прочитайте документацію наuseEffect .

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

Ви хочете використовувати useEffect(), яке, залежно від того, як ви використовуєте функцію, може діяти так само, як componentDidMount ().

Напр. Ви можете скористатися спеціальною loadedвластивістю стану, для якої спочатку встановлено значення false, і перемкнути її на true при отрисуванні, і запускати ефект лише тоді, коли це значення змінюється.

Документація


1
Це рішення не є ідеальним. Погано використовувати значення стану лише для того, щоб визначити, чи компонент змонтовано. Крім того, якщо ви хочете використовувати властивість, посилання було б краще, оскільки воно не спричинило б повторне рендеринг.
Yangshun Tay

0

точним еквівалентним хуком для componentDidMount () є

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

сподіваюся, це корисно :)

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.