Метод жизненного цикла ReactJS внутри функционального компонента
Вместо того чтобы писать свои компоненты внутри класса, я хотел бы использовать вместо этого функциональный синтаксис.
Как переопределить componentDidMount
, componentWillMount
внутри функциональных компонентов?
Это вообще возможно?
const grid = (props) => {
console.log(props);
let {skuRules} = props;
const componentDidMount = () => {
if(!props.fetched) {
props.fetchRules();
}
console.log('mount it!');
};
return(
<Content title="Promotions" breadcrumbs={breadcrumbs} fetched={skuRules.fetched}>
<Box title="Sku Promotion">
<ActionButtons buttons={actionButtons} />
<SkuRuleGrid
data={skuRules.payload}
fetch={props.fetchSkuRules}
/>
</Box>
</Content>
)
}
Ответы
Ответ 1
Вы можете использовать real-pure-lifecycle для добавления функций жизненного цикла к функциональным компонентам.
Пример:
import React, { Component } from 'react';
import lifecycle from 'react-pure-lifecycle';
const methods = {
componentDidMount(props) {
console.log('I mounted! Here are my props: ', props);
}
};
const Channels = props => (
<h1>Hello</h1>
)
export default lifecycle(methods)(Channels);
Ответ 2
Редактировать: С введением Hooks
стало возможным реализовать как поведение, так и состояние жизненного цикла в функциональном компоненте. В настоящее время
Хуки - это новое предложение функций, которое позволяет вам использовать состояние и другие функции React без написания класса. Они выпущены в React как часть v16.8.0
useEffect
можно использовать для репликации поведения жизненного цикла, а useState
можно использовать для сохранения состояния в функциональном компоненте.
Вы можете реализовать свой вариант использования в хуках, как
const grid = (props) => {
console.log(props);
let {skuRules} = props;
useEffect(() => {
if(!props.fetched) {
props.fetchRules();
}
console.log('mount it!');
}, []); // passing an empty array as second argument triggers the callback in useEffect only after the initial render thus replicating 'componentDidMount' lifecycle behaviour
return(
<Content title="Promotions" breadcrumbs={breadcrumbs} fetched={skuRules.fetched}>
<Box title="Sku Promotion">
<ActionButtons buttons={actionButtons} />
<SkuRuleGrid
data={skuRules.payload}
fetch={props.fetchSkuRules}
/>
</Box>
</Content>
)
}
useEffect
также может возвращать функцию, которая будет запущена, когда компонент отключен. Это может быть использовано, чтобы отписаться от слушателей. Может использоваться для репликации поведения componentWillUnmount
Например: componentWillUnmount
useEffect(() => {
window.addEventListener('unhandledRejection', handler);
return () => {
window.removeEventListener('unhandledRejection', handler);
}
}, [])
В качестве второго аргумента, если вы предоставляете значения, они будут сравниваться перед запуском обратного вызова, если это какое-либо изменение в любом из следующих
Например: componentDidUpdate
componentDidUpdate(prevProps, prevState) {
const { counter } = this.props;
if (this.props.counter !== nextProps.counter) {
// some action here
}
}
Эквивалент крючков
useEffect(() => {
// action here
}, [props.counter]);
До версии 16.7.0
Свойство функциональных компонентов заключается в том, что они не имеют доступа к функциям жизненного цикла Reacts или ключевому слову this
. Вам нужно расширить класс React.Component
если вы хотите использовать функцию жизненного цикла.
class Grid extends React.Component {
constructor(props) {
super(props)
}
componentDidMount () {
if(!this.props.fetched) {
this.props.fetchRules();
}
console.log('mount it!');
}
render() {
return(
<Content title="Promotions" breadcrumbs={breadcrumbs} fetched={skuRules.fetched}>
<Box title="Sku Promotion">
<ActionButtons buttons={actionButtons} />
<SkuRuleGrid
data={skuRules.payload}
fetch={props.fetchSkuRules}
/>
</Box>
</Content>
)
}
}
Функциональные компоненты полезны, когда вы хотите визуализировать ваш компонент без дополнительной логики.
Ответ 3
Решение первое: вы можете использовать новый реагирующий HOOKS API. В настоящее время в React v16.8.0
Хуки позволяют вам использовать больше возможностей Reacts без классов. Хуки предоставляют более прямой API для уже знакомых вам понятий React: реквизиты, состояние, контекст, ссылки и жизненный цикл. Hooks решает все проблемы, решаемые с помощью Recompose.
Примечание автора recompose
(acdlite, 25 октября 2018 г.):
Привет! Я создал Recompose около трех лет назад. Примерно через год я присоединился к команде React. Сегодня мы объявили о предложении для крючков. Hooks решает все проблемы, которые я пытался решить с помощью Recompose три года назад, и многое другое. Я буду прекращать активное обслуживание этого пакета (за исключением, возможно, исправлений или исправлений для совместимости с будущими выпусками React) и рекомендую вместо этого использовать Hooks. Ваш существующий код с Recompose все еще будет работать, только не ожидайте каких-либо новых функций.
Решение второе:
Если вы используете версию реагирования, которая не поддерживает хуки, не беспокойтесь, вместо этого используйте recompose
(служебный пояс React для функциональных компонентов и компонентов более высокого порядка.). Вы можете использовать recompose
для присоединения lifecycle hooks, state, handlers etc
К функциональному компоненту.
Вот компонент без рендеринга, который присоединяет методы жизненного цикла через HOC жизненного цикла (от перекомпоновки).
// taken from https://gist.github.com/tsnieman/056af4bb9e87748c514d#file-auth-js-L33
function RenderlessComponent() {
return null;
}
export default lifecycle({
componentDidMount() {
const { checkIfAuthed } = this.props;
// Do they have an active session? ("Remember me")
checkIfAuthed();
},
componentWillReceiveProps(nextProps) {
const {
loadUser,
} = this.props;
// Various 'indicators'..
const becameAuthed = (!(this.props.auth) && nextProps.auth);
const isCurrentUser = (this.props.currentUser !== null);
if (becameAuthed) {
loadUser(nextProps.auth.uid);
}
const shouldSetCurrentUser = (!isCurrentUser && nextProps.auth);
if (shouldSetCurrentUser) {
const currentUser = nextProps.users[nextProps.auth.uid];
if (currentUser) {
this.props.setCurrentUser({
'id': nextProps.auth.uid,
...currentUser,
});
}
}
}
})(RenderlessComponent);
Ответ 4
Если вам нужно использовать React LifeCycle, вам нужно использовать Class.
Образец:
import React, { Component } from 'react';
class Grid extends Component {
constructor(props){
super(props)
}
componentDidMount () { /* do something */ }
render () {
return <h1>Hello</h1>
}
}
Ответ 5
Вы можете использовать модуль create-реагировать-класса. Официальная документация
Конечно, вы должны сначала установить его
npm install create-react-class
Вот рабочий пример
import React from "react";
import ReactDOM from "react-dom"
let createReactClass = require('create-react-class')
let Clock = createReactClass({
getInitialState:function(){
return {date:new Date()}
},
render:function(){
return (
<h1>{this.state.date.toLocaleTimeString()}</h1>
)
},
componentDidMount:function(){
this.timerId = setInterval(()=>this.setState({date:new Date()}),1000)
},
componentWillUnmount:function(){
clearInterval(this.timerId)
}
})
ReactDOM.render(
<Clock/>,
document.getElementById('root')
)
Ответ 6
если вы используете реагирование 16.8, вы можете использовать реагирующие зацепки... Реактивные зацепки - это функции, которые позволяют вам "зацепиться" за состояние React и функции жизненного цикла из компонентов функций... документы
Ответ 7
Согласно документации:
import React, { useState, useEffect } from 'react'
// Similar to componentDidMount and componentDidUpdate:
useEffect(() => {
});
см. React документацию