Abr*_*rar 69 javascript jsx reactjs react-hooks
在React的官方文档中提到 -
如果您熟悉React类生命周期方法,则可以将useEffect Hook视为componentDidMount,componentDidUpdate和componentWillUnmount的组合.
我的问题是 - 我们如何componentWillMount()在钩子中使用lifecyle方法?
Bha*_*han 146
您不能在钩子中使用任何现有的生命周期方法(componentDidMount,componentDidUpdate,componentWillUnmount等).它们只能在类组件中使用.而Hooks只能用于功能组件.React doc下面的内容是什么
如果您熟悉React类生命周期方法,则可以将useEffect Hook视为componentDidMount,componentDidUpdate和componentWillUnmount的组合.
建议是,您可以在功能组件中从类组件模仿这些生命周期方法.
componentDidMount中的代码在安装组件时运行一次.useEffect挂钩等效于此行为
useEffect(() => {
// Your code here
}, []);
Run Code Online (Sandbox Code Playgroud)
注意这里的第二个参数(空数组).这只会运行一次.
如果没有第二个参数,将在组件的每个渲染上调用useEffect钩子,这可能是危险的.
useEffect(() => {
// Your code here
});
Run Code Online (Sandbox Code Playgroud)
componentWillUnmount用于清理(如删除事件列表器,取消计时器等).假设您要在componentDidMount中添加事件列表器,并在componentWillUnmount中将其重新转移,如下所示.
componentDidMount() {
window.addEventListener('mousemove', () => {})
}
componentWillUnmount() {
window.removeEventListener('mousemove', () => {})
}
Run Code Online (Sandbox Code Playgroud)
Hook相当于上面的代码
useEffect(() => {
window.addEventListener('mousemove', () => {});
// returned function will be called on component unmount
return () => {
window.removeEventListener('mousemove', () => {})
}
}, [])
Run Code Online (Sandbox Code Playgroud)
MIN*_* WU 31
根据reactjs.org所述,将来将不再支持componentWillMount。 https://reactjs.org/docs/react-component.html#unsafe_componentwillmount
无需使用componentWillMount。
如果要在组件安装之前做一些事情,只需在构造函数()中进行即可。
如果要发出网络请求,请不要在componentWillMount中进行。这是因为这样做会导致意外的错误。
网络请求可以在componentDidMount中完成。
希望能帮助到你。
于08/03/2019更新
您要求componentWillMount的原因可能是因为您想在渲染之前初始化状态。
只需在useState中执行即可。
const helloWorld=()=>{
const [value,setValue]=useState(0) //initialize your state here
return <p>{value}</p>
}
export default helloWorld;
Run Code Online (Sandbox Code Playgroud)
或者,例如,如果原始代码如下所示,则可能要在componentWillMount中运行一个函数:
componentWillMount(){
console.log('componentWillMount')
}
Run Code Online (Sandbox Code Playgroud)
使用钩子,您需要做的就是删除生命周期方法:
const hookComponent=()=>{
console.log('componentWillMount')
return <p>you have transfered componeWillMount from class component into hook </p>
}
Run Code Online (Sandbox Code Playgroud)
我只想在有关useEffect的第一个答案中添加一些内容。
useEffect(()=>{})
Run Code Online (Sandbox Code Playgroud)
useEffect在每个渲染器上运行,它是componentDidUpdate,componentDidMount和ComponentWillUnmount的组合。
useEffect(()=>{},[])
Run Code Online (Sandbox Code Playgroud)
如果我们在useEffect中添加一个空数组,则它仅在安装组件时运行。这是因为useEffect将比较传递给它的数组。因此它不必是一个空数组,它可以是不变的数组。例如,它可以是[1,2,3]或['1,2']。useEffect仍然仅在安装组件时运行。
是否要运行一次还是在每次渲染后运行取决于您。只要您知道自己在做什么,就忘记添加数组,这并不危险。
我创建了一个挂钩示例。请检查一下。
https://codesandbox.io/s/kw6xj153wr
于21/08/2019更新
自从我写下以上答案以来,这一直是白人。我认为您需要注意一些事项。使用时
useEffect(()=>{},[])
Run Code Online (Sandbox Code Playgroud)
当react比较您传递给数组[]的值时,它使用Object.is()进行比较。如果将对象传递给它,例如
useEffect(()=>{},[{name:'Tom'}])
Run Code Online (Sandbox Code Playgroud)
这与以下内容完全相同:
useEffect(()=>{})
Run Code Online (Sandbox Code Playgroud)
每次都会重新渲染,因为当Object.is()比较对象时,它将比较其引用而不是值本身。这与{} === {}返回false的原因相同,因为它们的引用不同。如果仍然要比较对象本身而不是引用,则可以执行以下操作:
useEffect(()=>{},[JSON.stringify({name:'Tom'})])
Run Code Online (Sandbox Code Playgroud)
jpm*_*rks 18
您可以破解 useMemo 钩子来模拟 componentWillMount 生命周期事件。做就是了:
const Component = () => {
useMemo(() => {
// componentWillMount events
},[]);
useEffect(() => {
// componentDidMount events
return () => {
// componentWillUnmount events
}
}, []);
};
Run Code Online (Sandbox Code Playgroud)
您需要在与您的状态交互的任何内容之前保留 useMemo 钩子。这不是它的意图,但它对我所有 componentWillMount 问题都有效。
这是有效的,因为 useMemo 不需要实际返回一个值,您实际上不必将它用作任何东西,但是因为它根据依赖项记住一个值,该值只会运行一次(“[]”)并且它位于我们的组件之上当组件在其他任何事情之前安装时运行一次。
Jir*_*hal 17
这是我如何使用useRef钩子在功能组件中模拟构造函数的方式:
function Component(props) {
const willMount = useRef(true);
if (willMount.current) {
console.log('This runs only once before rendering the component.');
willMount.current = false;
}
return (<h1>Meow world!</h1>);
}
Run Code Online (Sandbox Code Playgroud)
这是生命周期示例:
function RenderLog(props) {
console.log('Render log: ' + props.children);
return (<>{props.children}</>);
}
function Component(props) {
console.log('Body');
const [count, setCount] = useState(0);
const willMount = useRef(true);
if (willMount.current) {
console.log('First time load (it runs only once)');
setCount(2);
willMount.current = false;
} else {
console.log('Repeated load');
}
useEffect(() => {
console.log('Component did mount (it runs only once)');
return () => console.log('Component will unmount');
}, []);
useEffect(() => {
console.log('Component did update');
});
useEffect(() => {
console.log('Component will receive props');
}, [count]);
return (
<>
<h1>{count}</h1>
<RenderLog>{count}</RenderLog>
</>
);
}
Run Code Online (Sandbox Code Playgroud)
[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
Run Code Online (Sandbox Code Playgroud)
当然Class组件没有Body步骤,由于函数和类的概念不同,无法进行1:1的模拟。
lok*_*ngh 13
为了简单的视觉参考,请遵循此图像
正如您在上图中可以简单地看到,对于 ComponentWillUnmount,您必须这样做
useEffect(() => {
return () => {
console.log('componentWillUnmount');
};
}, []);
Run Code Online (Sandbox Code Playgroud)
Ben*_*arp 11
在大多数情况下useComponentDidMount是要使用的工具。组件安装(初始渲染)后,它将仅运行一次。
const useComponentDidMount = func => useEffect(func, []);
Run Code Online (Sandbox Code Playgroud)
重要的是要注意,在类中组件componentWillMount被认为是遗留的。如果您需要代码在组件安装之前仅运行一次,则可以使用构造函数。在这里了解更多。由于功能组件没有构造函数的等效性,因此在某些情况下使用钩子在组件挂载前仅运行一次代码可能是有意义的。您可以使用自定义钩子来实现。
const useComponentWillMount = func => {
const willMount = useRef(true);
if (willMount.current) {
func();
}
useComponentDidMount(() => {
willMount.current = false;
});
};
Run Code Online (Sandbox Code Playgroud)
但是,有一个陷阱。不要使用它来异步设置状态(例如在服务器请求之后。如您所料,它会影响初始渲染,而不会影响初始渲染)。此类情况应以处理useComponentDidMount。
const Component = (props) => {
useComponentWillMount(() => console.log("Runs only once before component mounts"));
useComponentDidMount(() => console.log("Runs only once after component mounts"));
...
return (
<div>{...}</div>
);
}
Run Code Online (Sandbox Code Playgroud)
useLayoutEffect[]如果功能实际上类似于componentWillMount-它可以在第一个内容到达DOM之前运行,则可以使用一组空的观察者()完成此操作–尽管实际上有两个更新,但是它们在绘制到屏幕之前是同步的。
例如:
function MyComponent({ ...andItsProps }) {
useLayoutEffect(()=> {
console.log('I am about to render!');
},[]);
return (<div>some content</div>);
}
Run Code Online (Sandbox Code Playgroud)
相useState对于使用初始化程序/设置程序的好处,或者useEffect尽管它可以计算渲染过程,但用户不会注意到对DOM的实际重新渲染,而是在第一个值得注意的渲染之前运行,而事实并非如此。useEffect。缺点当然是您的第一次渲染会稍有延迟,因为必须先进行检查/更新,然后才能绘画到屏幕上。不过,这确实取决于您的用例。
我个人认为,useMemo在某些小众情况下,您需要做一些繁重的事情是可以的-只要记住,这是例外而不是常规。
我写了一个自定义钩子,它将在第一次渲染之前运行一次函数。
useBeforeFirstRender.js
import { useState, useEffect } from 'react'
export default (fun) => {
const [hasRendered, setHasRendered] = useState(false)
useEffect(() => setHasRendered(true), [hasRendered])
if (!hasRendered) {
fun()
}
}
Run Code Online (Sandbox Code Playgroud)
用法:
import React, { useEffect } from 'react'
import useBeforeFirstRender from '../hooks/useBeforeFirstRender'
export default () => {
useBeforeFirstRender(() => {
console.log('Do stuff here')
})
return (
<div>
My component
</div>
)
}
Run Code Online (Sandbox Code Playgroud)
componentWillMount已弃用(1 , 2 , 3),并且建议的替换是在 constructor 仅在功能组件主体中运行一次函数。由于功能组件主体中的代码通常在每次重新渲染时运行,因此我们需要转向钩子。选项为useState、useMemo或useEffect,具体取决于用例所需的时间。
由于代码需要在初始渲染提交到屏幕之前useEffect运行,因此这不合格: \xe2\x80\x9c 传递给 useEffect 的函数将在渲染提交到屏幕后运行。\xe2\x80\x9d 4。
由于我们要保证代码只会运行一次并且不会被重新计算,因此这不符合条件useMemo:“将来,React 可能会选择 \xe2\x80\x9c 忘记\xe2\x80\x9d 一些以前记忆的值,并在下一次重新计算它们渲染” 5 .
useState支持惰性初始状态计算,保证在首次渲染功能组件时仅运行一次,这正是我们正在寻找的。
const runOnceBeforeRender = () => {};\n\nconst Component = () => {\n useState(runOnceBeforeRender);\n\n return (<></>);\n}\nRun Code Online (Sandbox Code Playgroud)\nconst runOnceBeforeRender = () => {};\n\nconst useOnInitialRender = (fn) => {\n useState(fn);\n}\n\nconst Component = () => {\n useOnInitialRender(runOnceBeforeRender);\n\n return (<></>);\n};\nRun Code Online (Sandbox Code Playgroud)\n该runOnceBeforeRender函数可以选择返回一个在函数第一次渲染时立即可用的值,而不会触发重新渲染。该值不会在后续渲染中重新计算。
const runOnceBeforeRender = () => 1 + 1;\n\nconst useOnInitialRender = (fn) => {\n const [value] = useState(fn);\n\n return value;\n}\n\nconst Component = () => {\n const value = useOnInitialRender(runOnceBeforeRender);\n\n return (<>{value}</>); // 2\n};\n\nRun Code Online (Sandbox Code Playgroud)\n一个(可能不必要的)NPM 包:useOnce 钩子
\n| 归档时间: |
|
| 查看次数: |
47733 次 |
| 最近记录: |