我目前正在“布局” componentDidMount上初始化相关的商店数据(图库和件)。这些数据是从API提取的。
const mapDispatchToProps = {
GetRooms,
GetPieces
}
class Layout extends React.Component {
...
componentDidMount () {
this.props.GetRooms()
this.props.GetPieces()
}
...
render () {
return (
...
<Route path="/Gallery/:roomName" component={Gallery} />
...
)
}
}
我有一个单独的“图库”组件,该组件通过Layout组件内的react-route路由加载。 Gallery的mapStateToProps使用选择器功能过滤请求的Gallery对象,并附加一个包含相关片断对象数组的属性。
const GetRoomByName = (state, roomName) => {
const room = state.rooms.all.find(room =>
room.Name === roomName
)
if (!room) return
room.Pieces = state.pieces.all.filter(piece =>
piece.RoomId === room.Id
)
return room
}
const mapStateToProps = (state, { match }) => ({
room: GetRoomByName(state, decodeURIComponent(match.params.roomName))
})
class Gallery extends React.Component {
...
render () {
const { room } = this.props
if (room === undefined) return <h3>Loading...</h3>
return (
...
{room.Pieces.map(piece =>
...
)}
...
)
}
}
当我从主页导航到此页面时,商店已经初始化并且选择器正确执行。
但是,如果刷新或加载了从地址栏中直接加载“图库”组件的路由,则存储中尚不存在数据,并且在加载时该组件也不会更新。我可以运行控制台日志,并渲染room对象,但是Pieces属性在加载到商店中时不会触发重新渲染。
谢谢您的帮助
答案 0 :(得分:0)
问题与connect
函数如何确定是否应重新呈现组件有关。 connect
仅在mapStateToProps
中的属性之一发生更改时才重新渲染该组件(使用浅表比较确定)。因为它使用浅表比较,所以除非GetRoomByName
返回的引用发生更改,否则组件不会重新呈现。要解决此问题,您应该从GetRoomByName
返回一个新对象,而不要修改状态中存在的对象(这可能会导致其他人也必须在以后诊断问题)。
const GetRoomByName = (state, roomName) => {
const room = state.rooms.all.find(room =>
room.Name === roomName
);
if (!room) return
const pieces = state.pieces.all.filter(piece =>
piece.RoomId === room.Id
);
return {
...room,
Pieces: pieces
};
}
这并不是很有效,因为它每次都会返回一个新对象,从而导致组件重新渲染的频率超过了必要。根据您的情况,这可能不是问题。如果是,则应查看reselect,它将缓存GetRoomByName
的结果。
此外,从首页导航时,您的代码有效的原因是,由于GetRoomByName
发生了变化,您返回的引用不同于roomName
。