Есть ли способы моделирования componentDidMount
функциональных компонентов React с помощью хуков?
Ответы:
Для стабильной версии хуков (React Version 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]);
Таким образом, всякий раз, когда ваш счетчик обновляется, ваш компонент будет повторно визуализироваться. Надеюсь, это немного поможет.
useState
. Всем, кто читает это, имейте в виду, что оставление второго аргумента undefined
приведет к срабатыванию вашего эффекта при каждом рендере (если я не ошибаюсь).
Хотя принятый ответ работает, это не рекомендуется. Если у вас более одного состояния и вы используете его с 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 в это время, но по мере роста вашего приложения есть вероятность, что вы МОЖЕТЕ столкнуться с некоторыми проблемами. Поэтому, чем переписывать на этом этапе, лучше сделать это на ранней стадии.
Кроме того, ООП не так уж и плох, если бы было достаточно процедурно-ориентированного программирования, у нас никогда бы не было объектно-ориентированного программирования. Иногда это больно, но лучше (технически не говоря уже о личных проблемах).
Там нет 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>
Вы хотите использовать useEffect()
, который, в зависимости от того, как вы используете функцию, может действовать так же, как componentDidMount ().
Например. вы можете использовать настраиваемое loaded
свойство состояния, для которого изначально установлено значение false, и переключить его на true при рендеринге и активировать эффект только при изменении этого значения.