对于类组件,this.setState如果在事件处理程序内部则调用批处理.但是如果在事件处理程序之外更新状态并使用'useState'钩子会发生什么?
function Component() {
const [a, setA] = useState('a');
const [b, setB] = useState('b');
function handleClick() {
Promise.resolve().then(() => {
setA('aa');
setB('bb');
});
}
return <button onClick={handleClick}>{a}-{b}</button>
}
Run Code Online (Sandbox Code Playgroud)
它会useState马上渲染吗?或者它会是aa - bb然后aa - b呢?
使用React的新效果钩子,如果重新渲染之间某些值没有改变,我可以告诉React跳过应用效果 - 来自React的文档示例:
useEffect(() => {
document.title = `You clicked ${count} times`;
}, [count]); // Only re-run the effect if count changes
Run Code Online (Sandbox Code Playgroud)
但是上面的例子应用了初始渲染时的效果,以及后续重新渲染的位置count.如何告诉React跳过初始渲染的效果?
基本上我们componentDidMount()在React类组件中的生命周期方法中进行API调用,如下所示
componentDidMount(){
//Here we do API call and do setState accordingly
}
Run Code Online (Sandbox Code Playgroud)
但是在React v16.7.0中引入了钩子之后,就没有更多的类组件了.
我的查询是,我们究竟需要在带有钩子的功能组件中进行API调用?
我们有类似的方法componentDidMount()吗?
我试图把头缠在新的react钩子api上。具体来说,我正在尝试构建一次经典的用例:
componentDidUpdate(prevProps) {
if (prevProps.foo !== this.props.foo) {
// animate dom elements here...
this.animateSomething(this.ref, this.props.onAnimationComplete);
}
}
Run Code Online (Sandbox Code Playgroud)
现在,我尝试使用功能组件和构建相同的组件useEffect,但不知道如何实现。这是我尝试的:
useEffect(() => {
animateSomething(ref, props.onAnimationComplete);
}, [props.foo]);
Run Code Online (Sandbox Code Playgroud)
这样,仅在props.foo更改时才调用效果。那确实有效–但是!由于将其eslint-plugin-react-hooks标记为错误,因此它似乎是反模式。效果内使用的所有依赖项都应在依赖项数组中声明。因此,这意味着我必须执行以下操作:
useEffect(() => {
animateSomething(ref, props.onAnimationComplete);
}, [props.foo, ref, props.onAnimationComplete]);
Run Code Online (Sandbox Code Playgroud)
但这不会导致掉毛错误,但完全无法实现仅在props.foo更改时调用效果的目的。我不希望在其他道具或裁判改变时调用它。
现在,我读到一些有关使用useCallback这种包装的信息。我试过了,但没有得到进一步的解决。
有人可以帮忙吗?
添加// eslint-disable-next-line react-hooks/exhaustive-deps我的代码后,我收到以下 eslint 错误。
8:14 未找到规则“react-hooks/exhaustive-deps”的错误定义
我参考了这篇文章来解决这个问题,但提到的解决方案在我的情况下不起作用。任何线索如何抑制这个eslint错误?
PS我结合使用standardjs。
这是我的自定义钩子:
export function useClientRect() {
const [scrollH, setScrollH] = useState(0);
const [clientH, setClientH] = useState(0);
const ref = useCallback(node => {
if (node !== null) {
setScrollH(node.scrollHeight);
setClientH(node.clientHeight);
}
}, []);
return [scrollH, clientH, ref];
}
}
Run Code Online (Sandbox Code Playgroud)
我希望每次调用它时,它都会返回我的值。喜欢:
jest.mock('useClientRect', () => [300, 200, () => {}]);
Run Code Online (Sandbox Code Playgroud)
我怎样才能做到这一点?
我经常按照“类架构”编写功能组件,其中所有与组件相关的函数都像类中的方法一样写在其中。
例如,我这里有一个counterAsFloat与Counter组件相关的函数。如您所见,我只是在组件内部编写了它:
export default function Counter() {
const [counter, setCounter] = React.useState(0);
const counterAsFloat = () => {
return counter.toFixed(2);
};
return (
<div className="counter">
<h1>{counterAsFloat()}</h1>
<button onClick={() => setCounter(counter + 1)}>
Increment
</button>
</div>
);
}
Run Code Online (Sandbox Code Playgroud)
但实际上我也可以只在组件外部声明函数并使用它的参数:
const counterAsFloat = (counter) => {
return counter.toFixed(2);
};
export default function Counter() {
const [counter, setCounter] = React.useState(0);
return (
<div className="counter">
<h1>{counterAsFloat(counter)}</h1>
<button onClick={() => setCounter(counter + 1)}>
Increment
</button>
</div>
);
}
Run Code Online (Sandbox Code Playgroud)
那么在功能组件之外编写函数有什么好处或坏处吗?
tldr; 如何模拟componentDidUpdate或以其他方式使用key数组来强制重置组件?
我正在实现一个显示计时器的组件,并在达到零时执行回调.目的是让回调更新对象列表.后一个组件由新的React钩子 useState和useEffect.
它state包含对计时器启动时间和剩余时间的引用.该effect套间隔称为每秒钟更新的剩余时间,并检查是否回调应该叫.
该组件并不意味着重新安排定时器,或者当它达到零时保持间隔,它应该执行回调和空闲.为了让计时器刷新,我希望传递一个数组,key这将导致组件的状态被重置,因此计时器将重新启动.不幸的是key必须与字符串一起使用,因此我的数组的引用是否已更改不会产生任何影响.
我还试图通过传递我关注的数组来推动对道具的更改,但状态得到维护,因此间隔未重置.
为了强制仅使用新的钩子API更新状态,在数组中观察浅层更改的首选方法是什么?
import React, { useState, useEffect } from 'react';
import PropTypes from 'prop-types';
function getTimeRemaining(startedAt, delay) {
const now = new Date();
const end = new Date(startedAt.getTime() + delay);
return Math.max(0, end.getTime() - now.getTime());
}
function RefresherTimer(props) {
const [startedAt, setStartedAt] = useState(new Date());
const [timeRemaining, setTimeRemaining] = useState(getTimeRemaining(startedAt, props.delay));
useEffect(() => {
if (timeRemaining <= 0) …Run Code Online (Sandbox Code Playgroud) 最近我正在阅读 react-redux 文档https://react-redux.js.org/next/api/hooks 并且有一个与平等比较和更新相关的部分,它说:
多次调用 useSelector(),每次调用返回一个字段值。
第一种方法:
const { open, importId, importProgress } = useSelector((importApp) => importApp.productsImport);
Run Code Online (Sandbox Code Playgroud)
第二种方法:
const open = useSelector((importApp) => importApp.productsImport.open);
const importId = useSelector((importApp) => importApp.productsImport.importId );
const importProgress = useSelector((importApp) => importApp.productsImport.importProgress);
Run Code Online (Sandbox Code Playgroud)
那么有什么真正的区别吗?或者由于破坏 useSelector 钩子会在检查引用时遇到麻烦?
有一些数据来自每 5 秒的长轮询,我希望我的组件在每次数组的一项(或数组长度本身)发生变化时分派一个动作。在将数组作为依赖项传递给 useEffect 时,如何防止 useEffect 进入无限循环,但如果任何值发生更改,仍然设法调度某些操作?
useEffect(() => {
console.log(outcomes)
}, [outcomes])
Run Code Online (Sandbox Code Playgroud)
其中outcomes是一组 ID,例如[123, 234, 3212]. 数组中的项目可能会被替换或删除,因此数组的总长度可能 - 但不必 - 保持不变,因此outcomes.length作为依赖传递不是这种情况。
outcomes 来自 reselect 的自定义选择器:
const getOutcomes = createSelector(
someData,
data => data.map(({ outcomeId }) => outcomeId)
)
Run Code Online (Sandbox Code Playgroud) react-hooks ×10
reactjs ×10
javascript ×5
eslint ×1
jestjs ×1
react-native ×1
react-redux ×1
standardjs ×1