Javascript 如何在React钩子中使用componentWillMount()?
React的官方文件中提到: 如果您熟悉React类生命周期方法,您可以 将效果挂钩用作componentDidMount、componentDidUpdate和 组件将联合卸载Javascript 如何在React钩子中使用componentWillMount()?,javascript,reactjs,jsx,react-hooks,Javascript,Reactjs,Jsx,React Hooks,React的官方文件中提到: 如果您熟悉React类生命周期方法,您可以 将效果挂钩用作componentDidMount、componentDidUpdate和 组件将联合卸载 我的问题是-我们如何在钩子中使用componentWillMount()lifecycle方法?根据reactjs.org,将来将不支持componentWillMount。 无需使用componentWillMount 如果要在安装组件之前执行某些操作,只需在构造函数()中执行即可 如果要执行网络请求,请不要在co
我的问题是-我们如何在钩子中使用
componentWillMount()
lifecycle方法?根据reactjs.org,将来将不支持componentWillMount。
无需使用componentWillMount
如果要在安装组件之前执行某些操作,只需在构造函数()中执行即可
如果要执行网络请求,请不要在componentWillMount中执行。这是因为这样做会导致意外的错误
网络请求可以在componentDidMount中完成
希望能有帮助
更新日期:2019年3月8日 您请求componentWillMount的原因可能是因为您希望在呈现之前初始化状态 就在你的状态下做吧
const helloWorld=()=>{
const [value,setValue]=useState(0) //initialize your state here
return <p>{value}</p>
}
export default helloWorld;
使用hook,您只需删除lifecycle方法:
const hookComponent=()=>{
console.log('componentWillMount')
return <p>you have transfered componeWillMount from class component into hook </p>
}
useEffect在每个渲染上运行,它是componentDidUpdate、componentDidMount和ComponentWillUnmount的组合
useEffect(()=>{},[])
如果我们在useffect中添加一个空数组,它将在安装组件时运行。这是因为useEffect将比较您传递给它的数组。
所以它不必是空数组,它可以是不变的数组。例如,它可以是[1,2,3]或['1,2']。useEffect仍仅在安装组件时运行
它取决于您希望它只运行一次还是在每次渲染后运行。如果您忘记添加数组,只要您知道自己在做什么,这并不危险
我为hook创建了一个示例。请检查一下
于2019年8月21日更新 我写上述答案已经有一段时间了。我认为你需要注意一些事情。 当你使用
useEffect(()=>{},[])
当react比较传递给数组[]的值时,它使用Object.is()
进行比较。
如果将对象传递给它,例如
useEffect(()=>{},[{name:'Tom'}])
这与:
useEffect(()=>{})
它每次都会重新渲染,因为当Object.is()
比较一个对象时,它比较的是它的引用,而不是值本身。这与{}=={}返回false的原因相同,因为它们的引用不同。
如果仍要比较对象本身而不是引用,可以执行以下操作:
componentWillMount(){
console.log('componentWillMount')
}
useEffect(()=>{},[JSON.stringify({name:'Tom'})])
const MyComp = () => {
const [state, setState] = useState(42) // set initial value directly in useState
const [state2, setState2] = useState(createInitVal) // call complex computation
return <div>{state},{state2}</div>
};
const createInitVal = () => { /* ... complex computation or other logic */ return 42; };
您不能在钩子中使用任何现有的生命周期方法(
componentDidMount
,componentdiddupdate
,componentWillUnmount
等)。它们只能在类组件中使用。对于挂钩,您只能在功能组件中使用。以下行来自React文档:
如果您熟悉React类生命周期方法,可以将useEffect
Hook看作是componentDidMount
,componentDidUpdate
,以及componentWillUnmount
的组合
建议是,您可以从功能组件中的类组件模拟这些生命周期方法
组件内部的代码在安装组件时运行一次<代码>使用效果此行为的挂钩等价物为
useEffect(() => {
// Your code here
}, []);
注意这里的第二个参数(空数组)。这将只运行一次
如果没有第二个参数则会在组件的每个渲染上调用useffect
钩子,这可能是危险的
useEffect(() => {
// Your code here
});
componentWillUnmount
用于清理(如删除事件侦听器、取消计时器等)。假设您正在componentDidMount
中添加事件侦听器,并在componentWillUnmount
中删除它,如下所示
componentDidMount() {
window.addEventListener('mousemove', () => {})
}
componentWillUnmount() {
window.removeEventListener('mousemove', () => {})
}
上述代码的等效吊钩如下所示
useEffect(() => {
window.addEventListener('mousemove', () => {});
// returned function will be called on component unmount
return () => {
window.removeEventListener('mousemove', () => {})
}
}, [])
请记住,传递给useMemo的函数在渲染期间运行。
不要在那里执行渲染时通常不会执行的任何操作。
例如,副作用属于useEffect,而不是useMemo
useLayoutEffect
可以通过一组空的观察者([]
)来实现这一点,如果该功能实际上类似于componentWillMount
——它将在第一个内容到达DOM之前运行——虽然实际上有两个更新,但它们在绘制到屏幕之前是同步的
例如:
function MyComponent({ ...andItsProps }) {
useLayoutEffect(()=> {
console.log('I am about to render!');
},[]);
return (<div>some content</div>);
}
函数MyComponent({…andItsProps}){
useLayoutEffect(()=>{
log('我将要渲染!');
},[]);
返回(某些内容);
}
使用初始化器/设置器或useffect
的useState
的好处在于,虽然它可以计算渲染过程,但用户不会注意到对DOM的实际重新渲染,并且它在第一次可注意到的渲染之前运行,useffect
的情况并非如此。当然,缺点是第一次渲染时会稍微延迟,因为在绘制到屏幕之前必须进行检查/更新。不过,这确实取决于您的用例
我个人认为,useMemo
在一些特殊情况下是可以的,在这些情况下,你需要做一些重要的事情——只要你记住这是一个例外,而不是正常情况。useComponentWillMount hook
const useComponentWillMount=(func)=>{
const willMount=useRef(真)
if(willMount.current)func()
willMount.current=false
}
我的经验是,当出现计时问题(在另一个脚本之前运行)时,这样的钩子可能是一种节省。如果不是这样,请使用更符合React-hooks范式的useComnponentDidMount
讨论
类内组件componentWillMount被视为遗留(,)。然而,这不应该应用于基于函数钩子的解决方案。类组件componentWillMount不推荐使用,因为它可能会运行多次,还有一种替代方法-使用构造函数。这些考虑因素并不重要
const Component = (props) => {
useComponentWillMount(() => console.log("Runs only once before component mounts"));
useComponentDidMount(() => console.log("Runs only once after component mounts"));
...
return (
<div>{...}</div>
);
}
import { useState, useEffect } from 'react'
export default (fun) => {
const [hasRendered, setHasRendered] = useState(false)
useEffect(() => setHasRendered(true), [hasRendered])
if (!hasRendered) {
fun()
}
}
import React, { useEffect } from 'react'
import useBeforeFirstRender from '../hooks/useBeforeFirstRender'
export default () => {
useBeforeFirstRender(() => {
console.log('Do stuff here')
})
return (
<div>
My component
</div>
)
}
useEffect(() => {
console.log('componentDidMount');
return () => {
console.log('componentWillUnmount');
};
}, []);
const InjectWillmount = function(Node, willMountCallback) {
let isCalled = true;
return function() {
if (isCalled) {
willMountCallback();
isCalled = false;
}
return Node;
};
};
const YourNewComponent = InjectWillmount(<YourComponent />, () => {
console.log("your pre-mount logic here");
});
const MyComp = () => {
const [state, setState] = useState(42) // set initial value directly in useState
const [state2, setState2] = useState(createInitVal) // call complex computation
return <div>{state},{state2}</div>
};
const createInitVal = () => { /* ... complex computation or other logic */ return 42; };
[Log] Body
[Log] First time load (it runs only once)
[Log] Body
[Log] Repeated load
[Log] Render log: 2
[Log] Component did mount (it runs only once)
[Log] Component did update
[Log] Component will receive props
useEffect(() => {
// Your code here
console.log("componentDidMount")
}, []);
const Component = () => {
useMemo(() => {
// componentWillMount events
},[]);
useEffect(() => {
// componentDidMount events
return () => {
// componentWillUnmount events
}
}, []);
};
const MyComponent = () => {
const [counter, setCounter] = useState(0)
useEffect(() => {
console.log('after render')
})
const iterate = () => {
setCounter(prevCounter => prevCounter+1)
}
const beforeRender = () => {
console.log('before render')
}
beforeRender()
return (
<div>
<div>{counter}</div>
<button onClick={iterate}>Re-render</button>
</div>
)
}
export default MyComponent
useEffect(() => {
return () => {
console.log('componentWillUnmount');
};
}, []);
useEffect(() => {
function handleStatusChange(status) {
setIsOnline(status.isOnline);
}
ChatAPI.subscribeToFriendStatus(props.friend.id, handleStatusChange);
// Specify how to clean up after this effect:
return function cleanup() {
ChatAPI.unsubscribeFromFriendStatus(props.friend.id, handleStatusChange);
};
});
if (isOnline === null) {
return 'Loading...';
}
return isOnline ? 'Online' : 'Offline';
}
const runOnceBeforeRender = () => {};
const Component = () => {
useState(runOnceBeforeRender);
return (<></>);
}
const runOnceBeforeRender = () => {};
const useOnInitialRender = (fn) => {
useState(fn);
}
const Component = () => {
useOnInitialRender(fn);
return (<></>);
};