如何使用 Redux 只更新组件的一个实例?
Posted
技术标签:
【中文标题】如何使用 Redux 只更新组件的一个实例?【英文标题】:How can I use Redux to only update one instance of a component? 【发布时间】:2021-01-16 14:37:25 【问题描述】:我正在尝试使用 Redux 来更新我的卡片组件以在点击时禁用和更改颜色。 Redux 可以很好地调度操作,但它会更新所有卡片,而不仅仅是被点击的卡片。每张卡片都有一个与之关联的对象,其中包含单词和值。该值是我想在单击时更改颜色的className
组件
const Card = ( wordObj, updateClass, isDisabled, cardClass ) =>
const showColor = (e) =>
updateClass(wordObj);
console.log(cardClass)
;
return (
<button
onClick=(e) => showColor()
disabled=isDisabled
className=cardClass>
wordObj.word
</button>
);
;
const mapStateToProps = (state) => (
cardClass: state.game.cardClass,
);
export default connect(mapStateToProps, updateClass )(Card);
动作
export const updateClass = (obj) => (dispatch) =>
console.log(obj)
dispatch(
type: UPDATE_CARD,
payload: obj,
);
;
减速器
const initialState =
words: [],
cardClass: 'card',
isDisabled: false,
;
export default function (state = initialState, action)
const type, payload = action;
switch (type)
case SET_WORDS:
return
...state,
words: payload,
;
case UPDATE_CARD:
return
...state,
isDisabled: true,
cardClass: ['card', payload.value].join(' '),
;
default:
return state;
```
【问题讨论】:
【参考方案1】:您的所有卡片组件都在使用状态中的相同 cardClass
字段。当你在这一行修改它时:
cardClass: ['card', payload.value].join(' ')
所有使用此字段的卡片都会更新其类别。 isDisable
字段也是如此。
您需要为您所在州的每张卡片创建一个对象。这是我的实现(未经测试):
const initialState =
cards: []
;
export default function (state = initialState, action)
const type, payload = action;
switch (type)
// create a card object for each word
case SET_WORDS:
return
...state,
cards: payload.map(word =>
return word: word, cardClass: "card", isDisabled: false
)
;
case UPDATE_CARD:
// here i'm using the wordObj.word passed as payload
// to identify the card (i recommend to use an id field)
const cardIndex = state.cards.findIndex(card => card.word === payload.word);
// get the current card
const card = state.cards[cardIndex];
// create an updated card object obeying the immutability principle
const updatedCard = ...card, isDisabled: true, cardClass: ['card', payload.value].join(' '),
return
...state,
cards: [
...state.cards.slice(0, cardIndex), // cards before
updatedCard,
...state.cards.slice(cardIndex + 1) // cards after
]
;
default:
return state;
【讨论】:
【参考方案2】:您的mapStateToProps
选择了一个string
,但是任何updateClass
上的字符串都发生了变化,这会导致您的所有卡片都更新,因为选择state.game.cardClass
会产生不同的值,这会触发新的渲染连接组件。
也许你想要的是识别选择的东西,即每张卡的 id,并在 mapStateToProps
中使用该 id 选择以避免读取更改,因为现在发生的情况如下:
卡 A[className="card A"] == 调度后 ==> mapStateToProps => [className="card B"] Card B[className="card A"] => dispatch('B') => mapStateToProps => [className="card B"]
B 正在更新 A 和 B 的状态,这就是发生 extra 渲染的原因
【讨论】:
以上是关于如何使用 Redux 只更新组件的一个实例?的主要内容,如果未能解决你的问题,请参考以下文章
如何在 React hooks 和 redux 中只获取一次且不再获取数据
在 React 中,如何在所有组件中拥有一个自定义钩子实例?