Redux中的状态发生更改,但未在组件中更新

时间:2020-09-22 09:19:37

标签: reactjs redux react-redux

我的redux商店更新完美

after sorting

before sorting

但是,即使商店已更新,我组件中的道具也不会更新,因此子组件仍显示旧值。我正在根据时间戳对频道进行排序。排序功能会更新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

0 个答案:

没有答案
相关问题