我想将前一个值存储在一个变量中并在函数中使用它。假设 当前值是 9,之前的值应该是 8(就像少一个) .问题是 console.log(prevServings)
在第一次渲染时返回 undefined 并在第二次渲染时显示前一个值,但是当前值和前一个值之间的差异是 2 而不是 1.我的理解是当前值在第一次渲染时不可用,因此前一个值未定义,但我不知道如何修复它。任何帮助,将不胜感激。提前致谢。
const Child = ({originalData}) =>{
//clone original data object with useState
const [copyData, setCopyDta] = useState({});
//clone the copied data
let duplicate = {...copyRecipe};
//store previous servings value into a variable
const usePrevious = (servings) => {
const ref = useRef();
useEffect(() => {
ref.current = servings;
}, [servings]);
return ref.current;
};
const prevServings = usePrevious(duplicate.servings);
//increase the number of servings on click
const incrementHandle = () => {
duplicate.servings = `${parseInt(duplicate.servings) + 1}`;
//this return undefined on the first render
console.log(prevServings);
setCopyRecipe(duplicate);
}
return(
<p>{copyData.servings}</p>
<Increment onClick={incrementHandle}/>
)
}
答案 0 :(得分:0)
它返回 undefined
因为 useEffect()
至少在第一次渲染之后才会触发。你可能想要这样做:
const usePrevious = (servings) => {
const ref = useRef(servings);
useEffect(() => {
ref.current = servings;
}, [servings])
return ref.current;
}
不过,这确实让人难以推理。我可能会建议改用减速器或常规状态。如果您不希望组件对该特定值的更改做出“反应”,则 ref 很有用,但是每次 ref 在这里更改时,您无论如何都会触发状态更新。
答案 1 :(得分:0)
糟糕,不是完全重复。这里的问题是,由于您已经声明了 usePrevious
inside 组件,它会在每个渲染周期重新创建,从而有效地否定了任何缓存工作。
将 usePrevious
钩子移出组件主体,使其成为一个稳定的参考。您可能还想删除 useEffect
的依赖项,以便在每个渲染周期缓存该值。
//store previous servings value into a variable
const usePrevious = (value) => {
const ref = useRef();
useEffect(() => {
ref.current = value;
});
return ref.current;
};
const Child = ({originalData}) =>{
//clone original data object with useState
const [copyData, setCopyDta] = useState({});
//clone the copied data
let duplicate = { ...copyData };
const prevServings = usePrevious(duplicate.servings);
//increase the number of servings on click
const incrementHandle = () => {
duplicate.servings = `${parseInt(duplicate.servings) + 1}`;
setCopyDta(duplicate);
}
return(
<p>{copyData.servings}</p>
<Increment onClick={incrementHandle}/>
)
}
仅供参考,let duplicate = { ...copyRecipe };
只是一个浅拷贝而不是对象的克隆,所有嵌套的属性仍将引用回原始对象中的对象。也许这就是你所需要的,但只是想指出这不是对象的真正克隆。
问题是 console.log(prevServings) 在 第一次渲染并在第二次渲染时显示前一个值
我认为这应该是预期的行为,因为在初始渲染时没有先前的渲染来缓存值。
<块引用>但是当前值和先前值之间的差为 2 共 1 个。
关于“off-by-2”问题,据我所知,每次渲染都会缓存 duplicate
的未更新浅表副本,当点击 incrementHandle
时,您会记录 {{1} } value 然后 将触发重新渲染的更新排入队列。您记录的值和状态更新结果(即 prevServings
)相隔两个渲染周期。如果在渲染周期的同一点比较两个值,您会发现它们相差 1。
<p>{copyData.servings}</p>
日志输出:
<块引用>useEffect(() => {
console.log({ prevServings, current: copyData.servings })
})