在React的功能组件中,有方法通过钩子来模拟componentDidMount吗?
当前回答
关于钩子内异步函数的信息:
效果回调是同步的,以防止竞争条件。把async函数放在里面:
useEffect(() => {
async function fetchData() {
// You can await here
const response = await MyAPI.getData(someId);
// ...
}
fetchData();
}, [someId]); // Or [] if effect doesn't need props or state
其他回答
对于钩子的稳定版本(React version 16.8.0+)
对于componentDidMount
useEffect(() => {
// Your code here
}, []);
对于componentDidUpdate
useEffect(() => {
// Your code here
}, [yourDependency]);
对于componentWillUnmount
useEffect(() => {
// componentWillUnmount
return () => {
// Your code here
}
}, [yourDependency]);
在这种情况下,你需要将你的依赖传递到这个数组中。假设有一个这样的状态
const [count, setCount] = useState(0);
当count增加时,你想重新渲染你的函数组件。然后你的useEffect应该看起来像这样
useEffect(() => {
// <div>{count}</div>
}, [count]);
这样,每当你的计数更新你的组件将重新呈现。希望这对你有所帮助。
componentDidMount()的等效钩子是
useEffect(()=>{},[]);
希望这对你有帮助。
import React, { useState, useEffect } from 'react';
function Example() {
const [count, setCount] = useState(0);
// Similar to componentDidMount and componentDidUpdate:
useEffect(() => {
// Update the document title using the browser API
document.title = `You clicked ${count} times`;
});
return (
<div>
<p>You clicked {count} times</p>
<button onClick={() => setCount(count + 1)}>
Click me
</button>
</div>
);
}
请访问这个官方文件。很容易理解最新的方式。
https://reactjs.org/docs/hooks-effect.html
useLayoutEffect钩子是React钩子中ComponentDidMount的最佳替代方案。 useLayoutEffect钩子在渲染UI之前执行,useEffect钩子在渲染UI之后执行。根据您的需要使用它。 示例代码:
import { useLayoutEffect, useEffect } from "react";
export default function App() {
useEffect(() => {
console.log("useEffect Statements");
}, []);
useLayoutEffect(() => {
console.log("useLayoutEffect Statements");
}, []);
return (
<div>
<h1>Hello Guys</h1>
</div>
);
}
是的,有一种方法可以在React功能组件中模拟componentDidMount
免责声明:这里真正的问题是您需要从“组件生命周期思维”转变为“useEffect思维”。
一个React组件仍然是一个javascript函数,所以,如果你想让某件事在另一件事之前执行,你必须简单地从上到下执行它,如果你认为它是一个函数,它仍然是一个函数,例如:
const myFunction = () => console.log('a')
const mySecondFunction = () => console.log('b)
mySecondFunction()
myFunction()
/* Result:
'b'
'a'
*/
这真的很简单,不是吗?
const MyComponent = () => {
const someCleverFunction = () => {...}
someCleverFunction() /* there I can execute it BEFORE
the first render (componentWillMount)*/
useEffect(()=> {
someCleverFunction() /* there I can execute it AFTER the first render */
},[]) /*I lie to react saying "hey, there are not external data (dependencies) that needs to be mapped here, trust me, I will leave this in blank.*/
return (
<div>
<h1>Hi!</h1>
</div>
)}
在这个特定的例子中,它是正确的。但是如果我这样做会发生什么:
const MyComponent = () => {
const someCleverFunction = () => {...}
someCleverFunction() /* there I can execute it BEFORE
the first render (componentWillMount)*/
useEffect(()=> {
someCleverFunction() /* there I can execute it AFTER the first render */
},[]) /*I lie to react saying "hey, there are not external data (dependencies) that needs to be maped here, trust me, I will leave this in blank.*/
return (
<div>
<h1>Hi!</h1>
</div>
)}
我们定义的“cleverFunction”在组件的每一次重渲染中都是不一样的。 这导致了一些严重的错误,在某些情况下,不必要的组件重渲染或无限的重渲染循环。
真正的问题是,React函数组件是一个根据你的状态多次“执行自己”的函数,这要归功于useEffect钩子(以及其他钩子)。
简而言之,useEffect是一个钩子,专门设计用于同步你的数据与你在屏幕上看到的任何东西。如果数据发生了变化,useEffect钩子需要始终知道这一点。这包括你的方法,因为它是数组依赖关系。 未定义会让你面临难以发现的漏洞。
正因为如此,了解这是如何工作的,以及你可以做些什么来以“反应”的方式得到你想要的东西是很重要的。
const initialState = {
count: 0,
step: 1,
done: false
};
function reducer(state, action) {
const { count, step } = state;
if (action.type === 'doSomething') {
if(state.done === true) return state;
return { ...state, count: state.count + state.step, state.done:true };
} else if (action.type === 'step') {
return { ...state, step: action.step };
} else {
throw new Error();
}
}
const MyComponent = () => {
const [state, dispatch] = useReducer(reducer, initialState);
const { count, step } = state;
useEffect(() => {
dispatch({ type: 'doSomething' });
}, [dispatch]);
return (
<div>
<h1>Hi!</h1>
</div>
)}
useReducer的分派方法是静态的,这意味着无论你的组件被重新渲染多少次,它都是相同的方法。因此,如果你只想执行某件事一次,而且你想在组件挂载之后立即执行,你可以像上面的例子那样做。这是一种正确的表述方式。
来源:The Complete Guide to useEffect - By Dan Abramov
也就是说,如果你喜欢实验东西,想知道如何做到“命令wat”,你可以使用useRef()与一个计数器或布尔值来检查ref是否存储了一个定义的引用,这是一个命令的方法,如果你不熟悉react背后发生的事情,建议避免使用它。
这是因为useRef()是一个钩子,它保存传递给它的参数,而不管呈现的数量(我保持简单,因为这不是问题的重点,你可以阅读这篇关于useRef的惊人文章)。所以这是知道组件第一次渲染发生的最佳方法。
我留下了一个例子,展示了同步“外部”效果(如外部函数)与“内部”组件状态的3种不同方法。
您可以在这里运行这个代码片段以查看日志并了解这3个函数何时执行。
const { useRef, useState, useEffect, useCallback } = React // External functions outside react component (like a data fetch) function renderOnce(count) { console.log(`renderOnce: I executed ${count} times because my default state is: undefined by default!`); } function renderOnFirstReRender(count) { console.log(`renderOnUpdate: I executed just ${count} times!`); } function renderOnEveryUpdate(count) { console.log(`renderOnEveryUpdate: I executed ${count ? count + 1 : 1} times!`); } const MyComponent = () => { const [count, setCount] = useState(undefined); const mounted = useRef(0); // useCallback is used just to avoid warnings in console.log const renderOnEveryUpdateCallBack = useCallback(count => { renderOnEveryUpdate(count); }, []); if (mounted.current === 0) { renderOnce(count); } if (mounted.current === 1) renderOnFirstReRender(count); useEffect(() => { mounted.current = mounted.current + 1; renderOnEveryUpdateCallBack(count); }, [count, renderOnEveryUpdateCallBack]); return ( <div> <h1>{count}</h1> <button onClick={() => setCount(prevState => (prevState ? prevState + 1 : 1))}>TouchMe</button> </div> ); }; class App extends React.Component { render() { return ( <div> <h1>hI!</h1> </div> ); } } ReactDOM.createRoot( document.getElementById("root") ).render( <MyComponent/> ); <div id="root"></div> <script src="https://cdnjs.cloudflare.com/ajax/libs/react/18.1.0/umd/react.development.js"></script> <script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/18.1.0/umd/react-dom.development.js"></script>
如果你执行它,你会看到如下内容:
推荐文章
- 给一个数字加上st, nd, rd和th(序数)后缀
- 如何以编程方式触发引导模式?
- setTimeout带引号和不带括号的区别
- 在JS的Chrome CPU配置文件中,'self'和'total'之间的差异
- 用javascript检查输入字符串中是否包含数字
- 如何使用JavaScript分割逗号分隔字符串?
- 在Javascript中~~(“双波浪号”)做什么?
- 谷歌chrome扩展::console.log()从后台页面?
- 未捕获的SyntaxError:
- [].slice的解释。调用javascript?
- jQuery日期/时间选择器
- 我如何预填充一个jQuery Datepicker文本框与今天的日期?
- npm犯错!代码UNABLE_TO_GET_ISSUER_CERT_LOCALLY
- 数组的indexOf函数和findIndex函数的区别
- 反应-显示加载屏幕,而DOM是渲染?