我应该在哪里声明在 useEffect() 挂钩中调用的函数?
Where should I declare functions that are called inside a useEffect() hook?
所以我在使用 useEffect
调用依赖于状态的函数时遇到以下情况。
示例:
// INSIDE APP COMPONENT
const [someState, setSomeState] = React.useState(0);
const [someTrigger, setSomeTrigger] = React.useState(false);
function someFunction() {
return someState + 1;
}
React.useEffect(() => {
const newState = someFunction(); // 'someFunction' IS BEING CALLED HERE
setSomeState(newState);
},[someTrigger])
问题:
在这种情况下,我应该在 useEffect()
内声明 someFunction
还是将其放在外面(但在组件主体内)是否安全?
我可以将它添加到 dependency
数组,但它会损害我的代码的可读性,因为我想专注于 trigger
.
由于 useEffect()
将在新渲染后 运行, 可以安全地假设它将具有我在其中调用的函数的新副本?
是否有关于何时应在 useEffect
挂钩内声明函数或何时必须将其添加到依赖项数组的基本规则?
编辑: 请注意,useEffect
必须具有这些函数的新副本,因为这些函数需要访问一些最新的 state
变量。
注意:
此代码在 CodeSandbox 上触发以下 eslint 警告。虽然它工作得很好。
React Hook React.useEffect has a missing dependency: 'someFunction'. Either include it or remove the dependency array. (react-hooks/exhaustive-deps)eslint
真实案例场景:
这是一个简化的例子。在我的真实案例中,这是一个带有过滤器组件的产品搜索页面。因此,当我单击过滤器以激活它时(比方说,price <= 50
),我触发了一个 useEffect()
,即 activePriceFilters
状态变量的 "listening"。然后该效果调用一个函数(示例中的 someFunction
),该函数将计算 filteredList
并将使用新的 filteredList
.
设置新的 productList
状态
片段
function App() {
const [someState, setSomeState] = React.useState(0);
const [someTrigger, setSomeTrigger] = React.useState(false);
function someFunction() {
return someState + 1;
}
React.useEffect(() => {
const newState = someFunction();
setSomeState(newState);
},[someTrigger])
return(
<React.Fragment>
<div>I am App</div>
<div>My state: {someState}</div>
<button onClick={()=>setSomeTrigger((prevState) => !prevState)}>Click</button>
</React.Fragment>
);
}
ReactDOM.render(<App/>, document.getElementById('root'));
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.8.3/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.8.3/umd/react-dom.production.min.js"></script>
<div id="root"/>
设置另一个状态应该根本没有效果。
const [someState, setSomeState] = React.useState(0);
function incrementState() {
setSomeState(someState => someState + 1);
}
在 useEffect 内部或外部定义函数取决于调用所有函数的位置。
如果您的函数仅从 useEffect 中调用,那么在 useEffect 中定义它是有意义的。
但是,从 useEffect 以及其他事件处理程序或其他效果中调用相同的函数,您需要在 useEffect 之外定义它
PS。在您的情况下,您只是更新不需要定义单独函数的状态
function App() {
const [someState, setSomeState] = React.useState(0);
const [someTrigger, setSomeTrigger] = React.useState(false);
React.useEffect(() => {
setSomeState(oldState => oldState + 1);
},[someTrigger])
return(
<React.Fragment>
<div>I am App</div>
<div>My state: {someState}</div>
<button onClick={()=>setSomeTrigger((prevState) => !prevState)}>Click</button>
</React.Fragment>
);
}
ReactDOM.render(<App/>, document.getElementById('root'));
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.8.3/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.8.3/umd/react-dom.production.min.js"></script>
<div id="root"/>
就你的场景而言,你会这样写
useEffect(() => {
const calcVal = (oldState) => {
// calculate previous state based on oldState
}
setSomeState(calcVal);
}, [activePriceFilters])
所以我在使用 useEffect
调用依赖于状态的函数时遇到以下情况。
示例:
// INSIDE APP COMPONENT
const [someState, setSomeState] = React.useState(0);
const [someTrigger, setSomeTrigger] = React.useState(false);
function someFunction() {
return someState + 1;
}
React.useEffect(() => {
const newState = someFunction(); // 'someFunction' IS BEING CALLED HERE
setSomeState(newState);
},[someTrigger])
问题:
在这种情况下,我应该在 useEffect()
内声明 someFunction
还是将其放在外面(但在组件主体内)是否安全?
我可以将它添加到 dependency
数组,但它会损害我的代码的可读性,因为我想专注于 trigger
.
由于 useEffect()
将在新渲染后 运行, 可以安全地假设它将具有我在其中调用的函数的新副本?
是否有关于何时应在 useEffect
挂钩内声明函数或何时必须将其添加到依赖项数组的基本规则?
编辑: 请注意,useEffect
必须具有这些函数的新副本,因为这些函数需要访问一些最新的 state
变量。
注意:
此代码在 CodeSandbox 上触发以下 eslint 警告。虽然它工作得很好。
React Hook React.useEffect has a missing dependency: 'someFunction'. Either include it or remove the dependency array. (react-hooks/exhaustive-deps)eslint
真实案例场景:
这是一个简化的例子。在我的真实案例中,这是一个带有过滤器组件的产品搜索页面。因此,当我单击过滤器以激活它时(比方说,price <= 50
),我触发了一个 useEffect()
,即 activePriceFilters
状态变量的 "listening"。然后该效果调用一个函数(示例中的 someFunction
),该函数将计算 filteredList
并将使用新的 filteredList
.
productList
状态
片段
function App() {
const [someState, setSomeState] = React.useState(0);
const [someTrigger, setSomeTrigger] = React.useState(false);
function someFunction() {
return someState + 1;
}
React.useEffect(() => {
const newState = someFunction();
setSomeState(newState);
},[someTrigger])
return(
<React.Fragment>
<div>I am App</div>
<div>My state: {someState}</div>
<button onClick={()=>setSomeTrigger((prevState) => !prevState)}>Click</button>
</React.Fragment>
);
}
ReactDOM.render(<App/>, document.getElementById('root'));
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.8.3/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.8.3/umd/react-dom.production.min.js"></script>
<div id="root"/>
设置另一个状态应该根本没有效果。
const [someState, setSomeState] = React.useState(0);
function incrementState() {
setSomeState(someState => someState + 1);
}
在 useEffect 内部或外部定义函数取决于调用所有函数的位置。
如果您的函数仅从 useEffect 中调用,那么在 useEffect 中定义它是有意义的。
但是,从 useEffect 以及其他事件处理程序或其他效果中调用相同的函数,您需要在 useEffect 之外定义它
PS。在您的情况下,您只是更新不需要定义单独函数的状态
function App() {
const [someState, setSomeState] = React.useState(0);
const [someTrigger, setSomeTrigger] = React.useState(false);
React.useEffect(() => {
setSomeState(oldState => oldState + 1);
},[someTrigger])
return(
<React.Fragment>
<div>I am App</div>
<div>My state: {someState}</div>
<button onClick={()=>setSomeTrigger((prevState) => !prevState)}>Click</button>
</React.Fragment>
);
}
ReactDOM.render(<App/>, document.getElementById('root'));
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.8.3/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.8.3/umd/react-dom.production.min.js"></script>
<div id="root"/>
就你的场景而言,你会这样写
useEffect(() => {
const calcVal = (oldState) => {
// calculate previous state based on oldState
}
setSomeState(calcVal);
}, [activePriceFilters])