因此,在使用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])
问题:
在这种情况下,我应该在someFunction
内声明useEffect()
还是将其保留在外部(但位于组件体内)是否安全?
我可以将其添加到dependency
数组中,但这会损害代码的可重复性,因为我想专注于trigger
。
由于useEffect()
将在新的渲染后运行,因此可以安全地假设它会具有我在其中调用的函数的新副本吗?
在何时应该在useEffect
钩子内声明函数或何时强制将其添加到依赖项数组中是否有基本规则?
编辑:请注意,useEffect
必须具有这些函数的新副本,因为这些函数需要访问一些最新的state
变量。
注意:
此代码在CodeSandbox上触发以下退出警告。虽然效果很好。
React Hook React.useEffect缺少依赖项:'someFunction'。包括它或删除依赖项数组。 (react-hooks / exhaustive-deps)eslint
真实案例场景:
这是一个简化的示例。实际上,这是一个包含过滤器组件的产品搜索页面。因此,当我单击一个过滤器以将其激活时(例如price <= 50
),我正在触发useEffect()
,它正在“监听” activePriceFilters
状态变量。然后,该效果调用一个函数(在示例中为someFunction
),该函数将计算filteredList
并使用新的productList
来设置新的filteredList
状态。
SNIPPET
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"/>
答案 0 :(得分:1)
设置其他状态根本不起作用。
const [someState, setSomeState] = React.useState(0);
function increaseState() {
setSomeState(someState + 1);
}
答案 1 :(得分: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])