[英]ReactJS lifecycle method inside a function Component
我不想在类中编写组件,而是使用函数语法。
如何在函数组件中覆盖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>
)
}
编辑:随着Hooks
的引入,可以实现生命周期类型的行为以及功能组件中的状态。 目前
Hooks 是一个新的特性提议,它允许你在不编写类的情况下使用状态和其他 React 特性。 它们作为v16.8.0的一部分在 React 中发布
useEffect
hook 可用于复制生命周期行为,而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
的行为:
例如: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
如果包含此数组,请确保包含组件范围内随时间变化的所有值(道具、状态),否则您最终可能会引用先前渲染中的值。
使用useEffect
有一些微妙之处; 在Here
查看 API。
v16.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>
)
}
}
当您只想渲染组件而不需要额外的逻辑时,函数组件很有用。
您可以使用react-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);
您可以使用钩子制作自己的“生命周期方法”,以获得最大的怀旧感。
实用功能:
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>;
};
解决方案一:您可以使用新的 react HOOKS API。 目前在React v16.8.0
Hooks 让你可以在没有类的情况下使用更多 React 的特性。 Hooks 为你已经知道的 React 概念提供了更直接的 API:props、state、context、refs 和生命周期。 Hooks 解决了 Recompose 解决的所有问题。
recompose
作者的注释(acdlite,2018 年 10 月 25 日):
你好! 大约三年前,我创建了 Recompose。 大约一年后,我加入了 React 团队。 今天,我们宣布了 Hooks 的提案。 Hooks 解决了我三年前尝试使用 Recompose 解决的所有问题,除此之外还有更多问题。 我将停止对该包的积极维护(可能不包括错误修复或与未来 React 版本兼容的补丁),并建议人们改用 Hooks。 您使用 Recompose 的现有代码仍然可以工作,只是不要期望任何新功能。
解决方案二:
如果您使用的是不支持 hooks 的 react 版本,不用担心,请使用recompose
(用于功能组件和高阶组件的 React 实用工具带。)。 您可以使用recompose
将lifecycle hooks, state, handlers etc
附加到功能组件。
这是一个无渲染组件,它通过生命周期 HOC(来自 recompose)附加生命周期方法。
// 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);
组件DidMount
useEffect(()=>{
// code here
})
组件WillMount
useEffect(()=>{
return ()=>{
//code here
}
})
组件DidUpdate
useEffect(()=>{
//code here
// when userName state change it will call
},[userName])
简短而甜蜜的答案
组件DidMount
useEffect(()=>{
// code here
})
组件WillUnmount
useEffect(()=>{
return ()=>{
//code here
}
})
组件DidUpdate
useEffect(()=>{
//code here
// when userName state change it will call
},[userName])
根据文档:
import React, { useState, useEffect } from 'react'
// Similar to componentDidMount and componentDidUpdate:
useEffect(() => {
});
参见反应文档
您可以使用 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 16.8,你可以使用 react Hooks ... React Hooks 是让你从函数组件“挂钩” React 状态和生命周期特性的函数...... docs
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;
与其将我的组件写在一个类中,我想使用函数语法。
如何重写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>
)
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.