我的redux商店更新完美
但是,即使商店已更新,我组件中的道具也不会更新,因此子组件仍显示旧值。我正在根据时间戳对频道进行排序。排序功能会更新redux存储,但仍会呈现未排序的数据。
the output it should be sorted but it remains the same(unsorted)
这是我的组件代码
export const RoomItem = (props) => {
const [roomLiveStatus, setRoomLiveStatus] = useState(false);
const compareTimestamp = (t1 = 0, t2 = 0) => {
return (t1.lastMessage && t2.lastMessage) && t2.lastMessage.timestamp - t1.lastMessage.timestamp
}
const getRoomData = () => {
const { roomData, workspace } = props;
const { workspaceId } = workspace
const workspaceIdLowerCase = workspaceId.toLowerCase()
const { roomId } = roomData;
const roomIdLowerCase = roomId.toLowerCase()
firebase
.firestore()
.collection(`sessions/${workspaceIdLowerCase}/rooms`)
.doc(`${roomIdLowerCase}`)
.onSnapshot(doc => {
if (doc.exists) {
// console.log("LIVE Sessions doc: ", doc.data())
const { currentSession } = doc.data()
if (currentSession !== "") {
setRoomLiveStatus(true)
} else {
setRoomLiveStatus(false)
}
}
})
}
useEffect(() => {
getRoomData();
},[])
useEffect(() => {
// do something
getRoomData();
// console.log(props,"props of roomitem")
},[props.sortType])
const strip = (value) => {
const { user, content } = value
let name = user.name;
let firstName = name.trim().split(" ")[0]
if (value.type === 0) {
if ( (firstName.length + content.length) > 32 ) {
let completeContent = `${firstName}: ${content}`
return `${completeContent.slice(0, 32)}...`
} else {
return `${firstName}: ${content}`
}
} else if (value.type === 1) {
return <span>{firstName}: <FontAwesomeIcon icon={faCalendarAlt} className="text-theme" /> Schedule</span>
} else if (value.type === 2) {
return (
<span>{firstName}: <FontAwesomeIcon icon={faClipboard} className="text-theme" />Files</span>
);
} else if (value.type === 3) {
return <span>{firstName}: <FontAwesomeIcon icon={faPoll} className="text-theme" /> Poll</span>
} else if (value.type === 4) {
return <span>{firstName}: <FontAwesomeIcon icon={faTasks} className="text-theme" /> Quiz</span>
} else if (value.type === 6) {
if ( (firstName.length + content.length) > 32) {
let len = 32 - firstName.length;
return <span>{firstName}: <FontAwesomeIcon icon={faImage} /> {content.length > len ? content.slice(0, len) + '…' : content}</span>
} else {
return <span>{firstName}: <FontAwesomeIcon icon={faImage} /> Photo</span>
}
} else if (value.type === 7) {
if ( (firstName.length + content.length) > 32) {
let len = 32 - firstName.length;
return <span>{firstName}: <FileIcon message={value} /> {content.length > len ? content.slice(0, len) + '…' : content}</span>
} else {
return <span>{firstName}: <FileIcon message={value} /> {value.metaData && value.metaData.name}</span>
}
} else if (value.type === 8) {
return <span>{content.length > 36 ? `${content.slice(0, 36)}...` : content}</span>
} else if (value.type === 9) {
return <span>{content.length > 36 ? `${content.slice(0, 36)}...` : content}</span>
} else {
return value.type
}
}
const {
key,
currentChannel,
workspaceData,
workspace,
setCurrentChannel,
setCurrentWorkspace,
setParticipants,
resetData
} = props;
const roomData = props.roomData;
const { roomId } = roomData;
return(
<li
className={currentChannel && (roomData.roomId === currentChannel.roomId)
? "active rounded-lg py-1 m-1 bg-card-theme shadow-sm text-theme"
: "rounded-lg py-1 m-1 bg-card-theme shadow-sm text-theme"}
key={key}
onClick={() => {
setCurrentChannel({ ...roomData, roomId })
setCurrentWorkspace({ ...workspaceData, ...workspace })
setParticipants(workspace.workspaceId, roomId)
resetData()
// setLeftPanel(!this.props.displayLeftPanel);
}}
name={roomData.roomName}
active={currentChannel && (roomData.roomId === currentChannel.roomId)}
>
<div className="d-flex align-items-center p-2 w-100">
<div className={roomLiveStatus ? "liveroom" : ""}>
<img
className={roomLiveStatus ? "mr-2 rounded-circle profile-image" : "mr-2 rounded-circle"}
src={roomData.roomPic}
style={{ height: 45, width: 45 }} />
</div>
<div className="flex-grow-1">
<div className="d-flex align-items-center">
{(roomData.roomType === 1)
&& <FontAwesomeIcon
icon={faLock}
className="text-success mr-2"
size="xs" />}
<p className="mb-0 text-theme">{roomData.roomName}</p>
</div>
{roomData.lastMessage
&& <small className="text-theme text-theme-lighter">
<span>{strip(roomData.lastMessage)}</span>
</small>}
</div>
<div className="text-right align-self-start">
{/* <FontAwesomeIcon
icon={faThumbtack}
style={isPinned ? { fontSize: 12, transform: "rotate(45deg)" } : { fontSize: 12 }}
className={isPinned ? "text-theme" : "text-secondary"} /> */}
<p
className="mb-0 text-theme small text-theme-lighter"
style={{ whiteSpace: "nowrap" }}
>
{roomData.lastMessage
&& timeFromNow(roomData.lastMessage.timestamp)}
</p>
{/* Messages Notification */}
{/* <span className="text-white bg-primary smaller font-weight-bold" style={{ whiteSpace: "nowrap", borderRadius: "2px", padding: "3px 3px 3px 3px" }}>
99+</span> */}
</div>
</div>
</li>
)
}
const WorkspaceListElement = (props) => {
const [workspaceData, setWorkspaceData] = useState({});
const [loadingWorkspaceData, setLoadingWorkspaceData] = useState(true);
const [roomsDataArray, setRoomsDataArray] = useState([]);
const [sortingCount, setSortingCount] = useState(0);
const getWorkspaceData = async () => {
const { workspace } = props;
let docRef = await firebase.firestore().collection(`workspaces`).doc(`${workspace.workspaceId}`)
let workspace_data = await docRef.get()
.then(function (doc) {
if (doc.exists) {
// console.log("Document data workspace:", doc.data());
const workspaceData = doc.data()
return workspaceData;
} else {
// doc.data() will be undefined in this case
console.log("No such document!");
}
})
.catch(function (error) {
console.log("Error getting document:", error);
})
setWorkspaceData(workspace_data);
setLoadingWorkspaceData(false);
}
const getAllRoomsData = () => {
const { workspace, roomsVisible, setChannels } = props
let roomsArray = []
let roomsDataPromises = []
let roomsDataArray = []
getWorkspaceData()
roomsArray = workspace[roomsVisible] && Object.values(workspace[roomsVisible]).map((room, key) => (
room.roomId
))
// console.log(`roomsArray ${JSON.stringify(roomsArray)}`)
roomsDataPromises = roomsArray.map((roomId, key) => firebase.firestore().collection(`workspaces/${workspace.workspaceId}/rooms`).doc(`${roomId}`).get())
Promise.all(roomsDataPromises).then(values => {
roomsDataArray = values.map(value => {
return { ...value.data(), roomId: value.id }
})
setChannels(roomsDataArray)
})
}
const {
workspace,
_handleAddRoom,
_handleOpenWorkspaceDetails,
roomsVisible,
currentChannel,
allChannels,
searchTerm,
sortType
} = props;
const regex = new RegExp(searchTerm, "gi");
useEffect(() => {
getAllRoomsData()
},[])
useEffect(() => {
getAllRoomsData()
},[props.roomsVisible, props.workspace[props.roomsVisible]])
useEffect(() => {
getWorkspaceData()
},[props.workspace])
useEffect(() => {
console.log('sorttype changed')
switchSort(allChannels, sortType)
setSortingCount((prev) => prev + 1)
},[sortType])
const compareTimestamp = (t1 = null, t2 = null) => {
if (t1 && t2) {return t2.timestamp - t1.timestamp}
if (t1 && t2 == null) {return -1}
if (t2 && t1 == null) {return 1}
return 0
}
const compareTimestampLodashLatestFirst = (allChannels) => {
const sorted = _.orderBy(allChannels, (channel) => {
})
props.setChannels(sorted);
return (sorted);
}
const compareAlphabetLodashAtoZ = (allChannels) => {
const sorted = _.sortBy(allChannels, (channel) => channel.roomName)
// console.log('atoz')
props.setChannels(sorted)
return (sorted);
}
const compareAlphabetLodashZtoA = (allChannels) => {
const sorted = _.sortBy(allChannels, (channel) => channel.roomName)
// console.log('ztoa')
props.setChannels(sorted.reverse())
return (sorted.reverse());
}
const switchSort = (allChannels, sortType) => {
// console.log(allChannels,"allChannels")
switch (sortType) {
case 0:
return compareTimestampLodashLatestFirst(allChannels)
case 1:
return compareAlphabetLodashAtoZ(allChannels)
case 2:
return compareAlphabetLodashZtoA(allChannels)
case 3:
return compareTimestampLodashLatestFirst(allChannels)
default:
return compareTimestampLodashLatestFirst(allChannels)
}
}
// console.log(allChannels,"before return")
return(
<>
{
searchTerm && searchTerm.length > 0
? allChannels
&& allChannels
.filter(item => {
return item.roomName.match(regex) || (item.lastMessage && item.lastMessage.content && item.lastMessage.content.match(regex))
})
.sort((a, b) => switchSort(a, b, sortType))
.map((room, key) => (
<RoomItem
roomData={room}
key={key}
index={key}
currentChannel={currentChannel}
workspace={workspace}
workspaceData={workspaceData}
allChannels={allChannels}
{...props}
/>
))
: allChannels &&
allChannels.map((room, key) => {
return(
<RoomItem
roomData={room}
key={room.roomName + key}
index={key}
currentChannel={currentChannel}
workspace={workspace}
workspaceData={workspaceData}
{...props}
/>
)
})
}
</>
)
}
const mapStateToProps = state => ({
roomsVisible: state.workspace.roomsVisible,
currentChannel: state.channel.currentChannel,
allChannels: state.channel.allChannels,
platform: state.channel.platform
})
export default connect(mapStateToProps, {
setChannels,
setCurrentChannel,
setCurrentWorkspace,
setParticipants,
resetData
})(WorkspaceListElement);
编辑:我通过使用lodash cloneDeep修复了它。如果有人遇到类似情况,请参考此react-redux update item in array doesn't re-render