功能组件中的ReactJS生命周期方法

我想使用函数语法,而不是在类中编写组件。

如何在函数组件内覆盖componentDidMountcomponentWillMount
有可能吗?

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>
)
}
194021 次浏览

编辑:通过引入Hooks,可以实现生命周期类型的行为以及功能组件中的状态。目前

钩子是一个新的功能提议,它允许您使用状态和其他 在不编写类的情况下反应功能。它们作为V16.8.0

的一部分在REACT中发布

useEffect挂钩可用于复制生命周期行为,useState可用于在功能组件中存储状态。

基本语法:

useEffect(callbackFunction, [dependentProps]) => cleanupFunction

你可以在钩子中实现你的用例,比如

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的行为:

例如:组件将卸载

useEffect(() => {
window.addEventListener('unhandledRejection', handler);
return () => {
window.removeEventListener('unhandledRejection', handler);
}
}, [])

要使useEffect以特定事件为条件,您可以为其提供一个值数组以检查更改:

例如:ComponentDidUpdate

componentDidUpdate(prevProps, prevState) {
const { counter } = this.props;
if (this.props.counter !== prevState.counter) {
// some action here
}
}

挂钩当量

useEffect(() => {
// action here
}, [props.counter]); // checks for changes in the values in this array

如果包含此数组,请确保包含组件范围中随时间变化的所有值(props、state),否则最终可能会引用以前渲染的值。

使用useEffect有一些微妙之处。查看APIHere


v16.7.0之前版本

功能组件的属性是它们无权访问反应生命周期功能或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>
)
}
}

当您只想呈现组件而不需要额外的逻辑时,函数组件非常有用。

您可以使用反应-纯生命周期向功能组件添加生命周期功能。

示例:

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);

您可以使用create-react-Class模块。 正式文件

当然,你必须先安装它。

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')
)

解决方案一: 您可以使用新的React钩子 API.目前处于反应v16.8.0

钩子可以让你在没有类的情况下使用更多的React特性。 钩子为您已经知道的React概念提供了更直接的API:props、state、context、refs和生命周期。 钩子解决了使用recompose解决的所有问题。

recompose的作者注释(ACDLITE,2018年10月25日):

嗨!我大约三年前创造了重组。大约一年后 之后,我加入了REACT团队。今天,我们宣布了一项提案 钩子。钩子解决了我试图解决的所有问题。 三年前重新组合,还有更多。我会的 停止此软件包的有效维护(可能不包括 与将来的React版本兼容的错误修复或修补程序),以及 建议人们用钩子代替。您的现有代码 重构仍然可以工作,只是不要期待任何新功能。

解决方案二:

如果您使用的是不支持挂钩的REACT版本,不用担心,请使用recompose(用于功能组件和高阶组件的REACT多用途带)。可以使用recomposelifecycle 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);

如果你使用反应16.8,你可以使用反应钩子.. React钩子是允许您从功能组件“钩入” React状态和生命周期功能的函数。 文件

根据文件:

import React, { useState, useEffect } from 'react'
// Similar to componentDidMount and componentDidUpdate:


useEffect(() => {




});

请参阅REACT文档

您可以创建自己的“生命周期方法”使用钩子最大怀旧。

实用程序功能:

import { useEffect, useRef } from "react";


export const useComponentDidMount = handler => {
return useEffect(() => handler(), []);
};


export const useComponentDidUpdate = (handler, deps) => {
const isInitialMount = useRef(true);


useEffect(() => {
if (isInitialMount.current) {
isInitialMount.current = false;


return;
}


return handler();
}, deps);
};


export const useComponentWillUnmount = handler => {
return useEffect(() => handler, []);
};


用法:

import {
useComponentDidMount,
useComponentDidUpdate,
useComponentWillUnmount
} from "./utils";


export const MyComponent = ({ myProp }) => {
useComponentDidMount(() => {
console.log("Component did mount!");
});


useComponentDidUpdate(() => {
console.log("Component did update!");
});


useComponentDidUpdate(() => {
console.log("myProp did update!");
}, [myProp]);


useComponentWillUnmount(() => {
console.log("Component will unmount!");
});


return <div>Hello world</div>;
};

ComponentDidMount

useEffect(()=>{
// code here
})

组件将安装

useEffect(()=>{


return ()=>{
//code here
}
})

组件更新

useEffect(()=>{


//code here
// when userName state change it will call
},[userName])

简短而甜蜜的回答

ComponentDidMount

useEffect(()=>{
// code here
})

组件将卸载

useEffect(()=>{


return ()=>{
//code here
}
})

组件更新

useEffect(()=>{


//code here
// when userName state change it will call
},[userName])
import React, { useState, useEffect } from "react";


const Counter = () => {
const [count, setCount] = useState(0);
const [count2, setCount2] = useState(0);


// componentDidMount
useEffect(() => {
console.log("The use effect ran");
}, []);


// // componentDidUpdate
useEffect(() => {
console.log("The use effect ran");
}, [count, count2]);


// componentWillUnmount
useEffect(() => {
console.log("The use effect ran");
return () => {
console.log("the return is being ran");
};
}, []);


useEffect(() => {
console.log(`The count has updated to ${count}`);
return () => {
console.log(`we are in the cleanup - the count is ${count}`);
};
}, [count]);


return (
<div>
<h6> Counter </h6>
<p> current count: {count} </p>
<button onClick={() => setCount(count + 1)}>increment the count</button>
<button onClick={() => setCount2(count2 + 1)}>increment count 2</button>
</div>
);
};


export default Counter;