kev*_*vin 3 reactjs react-hooks
为了便于阅读,我将在示例中删除很多功能。然而,本质上我有一个useEffect(如下所示),它具有跟踪state.cards卡对象数组的依赖项。我的假设是,如果该state.cards属性发生变化,则useEffect应该触发。然而,事实并非如此。
以下是正在使用的两种解决方案。我想使用第一个,因为它是恒定时间的。第二个虽然很好,但却是线性的。让我困惑的是为什么第二个选项会触发依赖关系,而第一个选项不会。两者都返回正确修改状态的克隆。
这不会触发 useEffect 依赖项state.cards。
const newArr = { ...state };
const matchingCard = newArr.cards[action.payload]; <-- payload = number
matchingCard.correct += 1;
matchingCard.lastPass = true;
return newArr;
Run Code Online (Sandbox Code Playgroud)
这确实会触发 useEffect 依赖项state.cards。
const newArr = { ...state };
const cards = newArr.cards.map((card) => {
if (card.id === action.payload.id) {
card.correct += 1;
card.lastPass = true;
}
return card;
});
return { ...newArr, cards };
Run Code Online (Sandbox Code Playgroud)
使用效果
useEffect(() => {
const passedCards = state.cards.filter((card) => {
return card.lastPass;
});
setLearnedCards(passedCards);
const calculatePercent = () => {
return (learnedCards.length / state.cards.length) * 100;
};
dispatch({ type: 'SET_PERCENT_COMPLETE', payload: calculatePercent() });
}, [learnedCards.length, state.cards]);
Run Code Online (Sandbox Code Playgroud)
状态
const initialState = {
cards: [], <-- each card will be an object
percentComplete: 0,
lessonComplete: false,
};
Run Code Online (Sandbox Code Playgroud)
解决方案:使用第一个示例的工作解决方案:
const newCardsArray = [...state.cards];
const matchingCard = newCardsArray[action.payload];
matchingCard.correct += 1;
matchingCard.lastPass = true;
return { ...state, cards: newCardsArray };
Run Code Online (Sandbox Code Playgroud)
原因:扩展数组state.cards会创建该数组的一个新的浅表副本。然后我可以对该克隆数组进行修改并将其作为分配给 的新值返回state.cards。扩展数组有一个新的引用,并且由 检测到useEffect。
我最好的猜测是,在第二个工作示例中 .map 返回一个带有新引用的新数组。在第一个示例中,您只是更改数组的内容,而不更改对该数组的引用。
我不太确定 useEffect 是如何比较的,但如果我没记错的话,对于一个对象来说,它只是关于该对象的引用。这有时会使在对象上使用 useEffect 变得困难。数组也可能是一样的。
你为什么不尝试一下:
const newCardsArray = [...state.cards]
// do your mutations here
Run Code Online (Sandbox Code Playgroud)
应该使用新的引用复制数组,就像对对象所做的那样。
| 归档时间: |
|
| 查看次数: |
5469 次 |
| 最近记录: |