当有多个 useEffects 时跳过第一个 useEffect
Skip first useEffect when there are multiple useEffects
要在第一次渲染时限制 运行 的 useEffect,我们可以这样做:
const isFirstRun = useRef(true);
useEffect (() => {
if (isFirstRun.current) {
isFirstRun.current = false;
return;
}
console.log("Effect was run");
});
根据这里的例子:
但是如果我的组件有多个 useEffects,每个 useEffects 处理不同的 useState 变化怎么办?我已经尝试在另一个 useEffect 中使用 isFirstRun.current
逻辑,但是由于一个 returns,另一个仍然在初始渲染上运行。
一些上下文:
const Comp = () => {
const [ amount, setAmount ] = useState(props.Item ? Item.Val : 0);
const [ type, setType ] = useState(props.Item ? Item.Type : "Type1");
useEffect(() => {
props.OnAmountChange(amount);
}, [amount]);
useEffect(() => {
props.OnTypeChange(type);
}, [type]);
return {
<>
// Radio button group for selecting Type
// Input field for setting Amount
</>
}
}
我对每个使用单独的 useEffects 的原因是,如果我执行以下操作,它不会更新数量。
useEffect(() => {
if (amount) {
props.OnAmountChange(amount);
} else if (type) {
props.OnTypeChange(type)
}
}, [amount, type]);
您可以使用单个 useEffect 来实现两种效果,您只是错误地实现了逻辑。
您最初的尝试:
useEffect(() => {
if (amount) {
props.OnAmountChange(amount);
} else if (type) {
props.OnTypeChange(type)
}
}, [amount, type]);
这里的问题是 if/elseif
,而是将它们视为独立的影响:
useEffect(() => {
if (amount !== 0) props.onAmountChange(amount);
if (type !== "Type1") props.onTypeChange(type);
}, [amount, type])
在此方法中,如果值与原始值不同,它将调用on change。但是,这有一个错误,如果用户将值切换回默认值,它将不起作用。所以我建议改为像这样实现整个代码:
const Comp = () => {
const [ amount, setAmount ] = useState(null);
const [ type, setType ] = useState(null);
useEffect(() => {
if (amount !== null) {
props.onAmountChange(amount);
} else {
props.onAmountChange(0);
}
}, [amount]);
useEffect(() => {
if (type !== null) {
props.onTypeChange(type);
} else {
props.onTypeChange("Type1");
}
}, [type]);
return (
<>
// Radio button group for selecting Type
// Input field for setting Amount
</>
)
}
通过使用 null
作为初始状态,您可以延迟调用 props
方法,直到用户在 Radio 中设置一个值来改变状态。
据我了解,您需要在第一次挂载和连续重新渲染时控制 useEffect 逻辑的执行。你想跳过第一个 useEffect。组件渲染后的效果 运行。
因此,如果您使用此解决方案:
const isFirstRun = useRef(true);
useEffect (() => {
if (isFirstRun.current) {
isFirstRun.current = false;
return;
}
console.log("Effect was run");
});
useEffect (() => {
// second useEffect
if(!isFirstRun) {
console.log("Effect was run");
}
});
所以在这种情况下,一旦 isFirstRun ref 设置为 false,对于所有连续效果,isFirstRun 的值变为 false,因此所有效果都将 运行。
你可以做的是,使用像 useMount 自定义 Hook 这样的东西,它可以告诉你它是第一次渲染还是连续的重新渲染。这是示例代码:
const {useState} = React
function useMounted() {
const [isMounted, setIsMounted] = useState(false)
React.useEffect(() => {
setIsMounted(true)
}, [])
return isMounted
}
function App() {
const [valueFirst, setValueFirst] = useState(0)
const [valueSecond, setValueSecond] = useState(0)
const isMounted = useMounted()
//1st effect which should run whenever valueFirst change except
//first time
React.useEffect(() => {
if (isMounted) {
console.log("valueFirst ran")
}
}, [valueFirst])
//2nd effect which should run whenever valueFirst change except
//first time
React.useEffect(() => {
if (isMounted) {
console.log("valueSecond ran")
}
}, [valueSecond])
return ( <
div >
<
span > {
valueFirst
} < /span> <
button onClick = {
() => {
setValueFirst((c) => c + 1)
}
} >
Trigger valueFirstEffect < /button> <
span > {
valueSecond
} < /span> <
button onClick = {
() => {
setValueSecond((c) => c + 1)
}
} >
Trigger valueSecondEffect < /button>
<
/div>
)
}
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"></div>
希望对您有所帮助!!
要在第一次渲染时限制 运行 的 useEffect,我们可以这样做:
const isFirstRun = useRef(true);
useEffect (() => {
if (isFirstRun.current) {
isFirstRun.current = false;
return;
}
console.log("Effect was run");
});
根据这里的例子:
但是如果我的组件有多个 useEffects,每个 useEffects 处理不同的 useState 变化怎么办?我已经尝试在另一个 useEffect 中使用 isFirstRun.current
逻辑,但是由于一个 returns,另一个仍然在初始渲染上运行。
一些上下文:
const Comp = () => {
const [ amount, setAmount ] = useState(props.Item ? Item.Val : 0);
const [ type, setType ] = useState(props.Item ? Item.Type : "Type1");
useEffect(() => {
props.OnAmountChange(amount);
}, [amount]);
useEffect(() => {
props.OnTypeChange(type);
}, [type]);
return {
<>
// Radio button group for selecting Type
// Input field for setting Amount
</>
}
}
我对每个使用单独的 useEffects 的原因是,如果我执行以下操作,它不会更新数量。
useEffect(() => {
if (amount) {
props.OnAmountChange(amount);
} else if (type) {
props.OnTypeChange(type)
}
}, [amount, type]);
您可以使用单个 useEffect 来实现两种效果,您只是错误地实现了逻辑。
您最初的尝试:
useEffect(() => {
if (amount) {
props.OnAmountChange(amount);
} else if (type) {
props.OnTypeChange(type)
}
}, [amount, type]);
这里的问题是 if/elseif
,而是将它们视为独立的影响:
useEffect(() => {
if (amount !== 0) props.onAmountChange(amount);
if (type !== "Type1") props.onTypeChange(type);
}, [amount, type])
在此方法中,如果值与原始值不同,它将调用on change。但是,这有一个错误,如果用户将值切换回默认值,它将不起作用。所以我建议改为像这样实现整个代码:
const Comp = () => {
const [ amount, setAmount ] = useState(null);
const [ type, setType ] = useState(null);
useEffect(() => {
if (amount !== null) {
props.onAmountChange(amount);
} else {
props.onAmountChange(0);
}
}, [amount]);
useEffect(() => {
if (type !== null) {
props.onTypeChange(type);
} else {
props.onTypeChange("Type1");
}
}, [type]);
return (
<>
// Radio button group for selecting Type
// Input field for setting Amount
</>
)
}
通过使用 null
作为初始状态,您可以延迟调用 props
方法,直到用户在 Radio 中设置一个值来改变状态。
据我了解,您需要在第一次挂载和连续重新渲染时控制 useEffect 逻辑的执行。你想跳过第一个 useEffect。组件渲染后的效果 运行。
因此,如果您使用此解决方案:
const isFirstRun = useRef(true);
useEffect (() => {
if (isFirstRun.current) {
isFirstRun.current = false;
return;
}
console.log("Effect was run");
});
useEffect (() => {
// second useEffect
if(!isFirstRun) {
console.log("Effect was run");
}
});
所以在这种情况下,一旦 isFirstRun ref 设置为 false,对于所有连续效果,isFirstRun 的值变为 false,因此所有效果都将 运行。
你可以做的是,使用像 useMount 自定义 Hook 这样的东西,它可以告诉你它是第一次渲染还是连续的重新渲染。这是示例代码:
const {useState} = React
function useMounted() {
const [isMounted, setIsMounted] = useState(false)
React.useEffect(() => {
setIsMounted(true)
}, [])
return isMounted
}
function App() {
const [valueFirst, setValueFirst] = useState(0)
const [valueSecond, setValueSecond] = useState(0)
const isMounted = useMounted()
//1st effect which should run whenever valueFirst change except
//first time
React.useEffect(() => {
if (isMounted) {
console.log("valueFirst ran")
}
}, [valueFirst])
//2nd effect which should run whenever valueFirst change except
//first time
React.useEffect(() => {
if (isMounted) {
console.log("valueSecond ran")
}
}, [valueSecond])
return ( <
div >
<
span > {
valueFirst
} < /span> <
button onClick = {
() => {
setValueFirst((c) => c + 1)
}
} >
Trigger valueFirstEffect < /button> <
span > {
valueSecond
} < /span> <
button onClick = {
() => {
setValueSecond((c) => c + 1)
}
} >
Trigger valueSecondEffect < /button>
<
/div>
)
}
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"></div>
希望对您有所帮助!!