为啥我的组件基于 redux 的 props 没有更新?
Posted
技术标签:
【中文标题】为啥我的组件基于 redux 的 props 没有更新?【英文标题】:Why are my component's redux-based props not updating?为什么我的组件基于 redux 的 props 没有更新? 【发布时间】:2021-01-21 15:24:06 【问题描述】:在将数据存储在 redux 存储和 firebase firestore 中的 react-native 应用程序中,我有一个 onSnapshot 监听器,它监听一个集合。在这个集合中的每个文档中,都有一个具有几个属性的对象,这些属性会随着时间的推移而改变。理想情况下,当这些对象属性值之一发生变化时,它应该反映在 redux 存储中,从而反映在 UI 中。问题是,当这些值之一发生变化时,redux 存储不会更新。
听众:
export const onAgendaChange = (uid, role, dispatch) =>
let query;
if (role == 'A')
query = 'a.uid';
else
query = 'b.uid';
console.log('(actions/agenda) Firestore Read: getAgenda()');
return firebase
.firestore()
.collection('events')
.where(query, '==', uid)
.orderBy('date')
.onSnapshot((querySnapshot) =>
const agenda = []
querySnapshot.docChanges().forEach(change =>
console.log(`change: $change.type`) // does not log anything
)
querySnapshot.forEach((doc) =>
let event = doc.data();
event.id = doc.id;
agenda.push(event);
dispatch( type: types.LOAD_AGENDA_SUCCESS, payload: agenda );
);
);
;
减速器:
const INITIAL_STATE =
loading: false,
events: []
;
export default (state = INITIAL_STATE, action) =>
switch (action.type)
case types.LOAD_AGENDA:
return
...state,
loading: true
;
case types.LOAD_AGENDA_SUCCESS:
return
loading: false,
events: action.payload
;
default:
return
...state
;
;
使用此数据的屏幕组件:
<View style=styles.container>
<FlatList
data=this.props.events
extraData=this.props
keyExtractor=(item) =>
return (
item.toString() +
new Date().getTime().toString() +
Math.floor(Math.random() * Math.floor(new Date().getTime())).toString()
);
renderItem=( item, index ) =>
const title = this.props.role == 'A' ? item.b.legalName : item.a.legalName;
const participantCheckInStatus =
this.props.role == 'A' ? item.checkedIn.b : item.checkedIn.a;
const currentUserCheckInStatus =
this.props.role == 'A' ? item.checkedIn.a : item.checkedIn.b;
console.log("agenda type B: " + item.checkedIn.b + " agenda type A: " + item.checkedIn.a)
return (
<Components.AgendaItem
title=title
participant=participantCheckInStatus
checkedIn=currentUserCheckInStatus
navigation=this.props.navigation
evnt=item
/>
);
/>
</View>
此集合中的文档结构类似于:
exampleMap: a: false, b: false ,
string: '',
string: '',
map: ... ,
map: ...
其他说明:
无论是通过操作还是从 Firebase 控制台更新文档,在 Firestore 中都成功更新了文档 即使刷新了 React Native 应用程序,使用相关数据的组件也不会更新 我有另一个包含地图的文档集。当更改此其他集合的映射中的值时,使用此数据的组件会正确更新。它们有相似的 reducer,两个 reducer 都是持久化的,而且监听器是相同的。 我还在我提到的这些相关减速器上使用 redux-persist,包括工作和非工作减速器 我正在使用 redux-thunk特殊观察:
组件正确接收道具更新的唯一时间是应用程序安装是否是新的,这意味着该应用程序已被删除并新安装在模拟器上。任何后续运行,道具数据都不会更新。我已经在使用这个 redux 存储的父组件和子组件中确认,当我在 firebase 控制台中更改值时,文档的 exampleMap
子属性值在 redux 中不会改变。所以我玩弄了 FlatList 的 extraData
道具,但无济于事。
无论如何,对于如何将这些更改带到 redux 商店有什么想法吗?
【问题讨论】:
请编辑问题以显示未按您期望的方式运行的代码,包括对 docChanges() 的调用,以便我们可以看到您正确使用它。 @DougStevenson 当然,但请记住,重点是使其成为 redux 的更新,而不是docChanges()
的非工作性质
【参考方案1】:
这是给你带来问题的部分:
.onSnapshot((querySnapshot) =>
const agenda = []
querySnapshot.docChanges().forEach(change =>
console.log(`change: $change.type`) // does not log anything
)
querySnapshot.forEach((doc) =>
let event = doc.data();
event.id = doc.id;
agenda.push(event);
dispatch( type: types.LOAD_AGENDA_SUCCESS, payload: agenda );
);
);
问题是您正在为后续调度重复使用相同的 agenda
数组 - 在中间修改它。
在你的减速器中
case types.LOAD_AGENDA_SUCCESS:
return
loading: false,
events: action.payload
你只是在为这个对象设置事件——这意味着当 react-redux 将旧的 events
与新的 events
进行比较时,它是对同一个对象的引用。 RR 看不出有什么不同。
解决此问题的方法是在将该数组保存到您的商店之前对其进行复制:
case types.LOAD_AGENDA_SUCCESS:
return
loading: false,
events: [...action.payload]
【讨论】:
【参考方案2】:需要在reducer中做如下改动:
case types.LOAD_AGENDA_SUCCESS:
return ...state, loading: false, events: [...action.payload] ;
因为您的屏幕组件会检查 events
道具的引用以确定是否重新渲染,因此您可以通过使用扩展运算符更改引用来解决此问题,如上所示。
此外,您应该将dispatch
调用转移到forEach
循环之外,以便agenda
数组仅与其中的所有项目一起发送到reducer,而不是为每个项目一次又一次地发送:
querySnapshot.forEach((doc) =>
let event = doc.data();
event.id = doc.id;
agenda.push(event);
);
dispatch( type: types.LOAD_AGENDA_SUCCESS, payload: agenda );
【讨论】:
以上是关于为啥我的组件基于 redux 的 props 没有更新?的主要内容,如果未能解决你的问题,请参考以下文章
在 Redux 将 Redux State 映射到 Props 后设置组件状态
Vue.js 父子组件,为啥我的 prop 在子组件中还没有?
React 类组件和 React 功能组件更改 redux store 后访问 props 的区别