Javascript 如何使用 React useEffect 调用加载函数一次
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/53120972/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
How to call loading function with React useEffect only once
提问by Dávid Molnár
The useEffectReact hook will run the passed in function on every change. This can be optimized to let it call only when the desired properties change.
该useEffect阵营钩将运行在功能上传递的每一个变化。这可以被优化以让它仅在所需的属性发生变化时调用。
What if I want to call an initialization function from componentDidMountand not call it again on changes? Let's say I want to load an entity, but the loading function doesn't need any data from the component. How can we make this using the useEffecthook?
如果我想调用初始化函数componentDidMount而不是在更改时再次调用它怎么办?假设我想加载一个实体,但加载函数不需要来自组件的任何数据。我们如何使用useEffect钩子做到这一点?
class MyComponent extends React.PureComponent {
componentDidMount() {
loadDataOnlyOnce();
}
render() { ... }
}
With hooks this could look like this:
使用钩子,这可能如下所示:
function MyComponent() {
useEffect(() => {
loadDataOnlyOnce(); // this will fire on every change :(
}, [...???]);
return (...);
}
回答by Tholle
If you only want to run the function given to useEffectafter the initial render, you can give it an empty array as second argument.
如果您只想useEffect在初始渲染后运行给定的函数,您可以给它一个空数组作为第二个参数。
function MyComponent() {
useEffect(() => {
loadDataOnlyOnce();
}, []);
return <div> {/* ... */} </div>;
}
回答by Edan Chetrit
TL;DR
TL; 博士
useEffect(yourCallback, [])- will trigger the callback only after the first render.
useEffect(yourCallback, [])- 只有在第一次渲染后才会触发回调。
Detailed explanation
详细说明
useEffectruns by default after everyrender of the component (thus causing an effect).
useEffect默认情况下在每次渲染组件后运行(从而产生效果)。
When placing useEffectin your component you tell React you want to run the callback as an effect. React will run the effect after rendering and after performing the DOM updates.
当放置useEffect在你的组件中时,你告诉 React 你想要运行回调作为效果。React 将在渲染和执行 DOM 更新后运行效果。
If you pass only a callback - the callback will run after each render.
如果您只传递一个回调 - 回调将在每次渲染后运行。
If passing a second argument (array), React will run the callback after the first render and every time one of the elements in the array is changed. for example when placing useEffect(() => console.log('hello'), [someVar, someOtherVar])- the callback will run after the first render and after any render that one of someVaror someOtherVarare changed.
如果传递第二个参数(数组),React 将在第一次渲染之后运行回调,并且每次更改数组中的一个元素。例如在放置时useEffect(() => console.log('hello'), [someVar, someOtherVar])- 回调将在第一次渲染之后运行,并且在任何渲染之后运行someVar或someOtherVar更改。
By passing the second argument an empty array, React will compare after each render the array and will see nothing was changed, thus calling the callback only after the first render.
通过向第二个参数传递一个空数组,React 将在每次渲染数组后进行比较,并且不会看到任何更改,因此仅在第一次渲染后调用回调。
回答by Ben Carp
useMountEffect hook
使用MountEffect 钩子
Running a function only once after component mounts is such a common pattern that it justifies a hook of it's own that hides implementation details.
在组件挂载后只运行一次函数是一种常见的模式,它证明了它自己的隐藏实现细节的钩子是合理的。
const useMountEffect = (fun) => useEffect(fun, [])
Use it in any functional component.
在任何功能组件中使用它。
function MyComponent() {
useMountEffect(function) // function will run only once after it has mounted.
return <div>...</div>;
}
About the useMountEffect hook
关于 useMountEffect 钩子
When using useEffectwith a second array argument, React will run the callback after mounting (initial render) and after values in the array have changed. Since we pass an empty array, it will run only after mounting.
当useEffect与第二个数组参数一起使用时,React 将在挂载(初始渲染)和数组中的值更改后运行回调。由于我们传递了一个空数组,它只会在挂载后运行。
回答by Yangshun Tay
Pass an empty array as the second argument to useEffect. This effectively tells React, quoting the docs:
将一个空数组作为第二个参数传递给useEffect. 这有效地告诉 React,引用文档:
This tells React that your effect doesn't depend on any values from props or state, so it never needs to re-run.
这告诉 React 你的 effect 不依赖于来自 props 或 state 的任何值,所以它永远不需要重新运行。
Here's a snippet which you can run to show that it works:
这是一个片段,您可以运行它以表明它有效:
function App() {
const [user, setUser] = React.useState(null);
React.useEffect(() => {
fetch('https://randomuser.me/api/')
.then(results => results.json())
.then(data => {
setUser(data.results[0]);
});
}, []); // Pass empty array to only run once on mount.
return <div>
{user ? user.name.first : 'Loading...'}
</div>;
}
ReactDOM.render(<App/>, document.getElementById('app'));
<script src="https://unpkg.com/[email protected]/umd/react.development.js"></script>
<script src="https://unpkg.com/[email protected]/umd/react-dom.development.js"></script>
<div id="app"></div>
回答by ecoologic
I like to define a mountfunction, it tricks EsLint in the same way useMountdoes and I find it more self-explanatory.
我喜欢定义一个mount函数,它以同样的方式欺骗 EsLint useMount,我发现它更不言自明。
const mount = () => {
console.log('mounted')
// ...
const unmount = () => {
console.log('unmounted')
// ...
}
return unmount
}
useEffect(mount, [])
回答by Farrukh Malik
The trick is that useEffect takes a second parameter.
诀窍是 useEffect 需要第二个参数。
The second param is an array of variables that the component will check to make sure it changed before re-rendering. You could put whatever bits of props and state you want in here to check against.
第二个参数是一个变量数组,组件将检查这些变量以确保它在重新渲染之前发生了变化。你可以在这里放任何你想要的道具和状态来检查。
Or, put nothing:
或者,什么都不放:
import React, { useEffect } from 'react';
function App() {
useEffect(() => {
// Run! Like go get some data from an API.
}, []); //Empty array as second argument
return (
<div>
{/* Do something with data. */}
</div>
);
}
That will ensure the useEffect only runs once.
这将确保 useEffect 只运行一次。
Note from the docs:
文档中的注释:
If you use this optimization, make sure the array includes all values from the component scope (such as props and state) that change over time and that are used by the effect. Otherwise, your code will reference stale values from previous renders.
如果您使用此优化,请确保数组包含组件范围内的所有值(例如 props 和 state),这些值随时间变化并被效果使用。否则,您的代码将引用先前渲染中的陈旧值。

