React (Next) 不会在 redux 状态更改后重新渲染(是的,状态作为新对象返回)
React (Next) won't re-render after redux state change (yes, state returned as new object)
我的 NextJS 应用程序发生状态更改后,重新呈现 时遇到问题。
函数 sendMessageForm
启动一个 redux 动作 sendMessage
将消息添加到状态。
问题与减速器中的返回状态无关,因为我正在返回一个新对象(return {...state}
),它应该触发重新渲染!
有什么可能会阻止重新渲染吗?
这是调用和显示状态的文件,所以没有其他文件应该负责!但如果您认为问题可能出在其他地方,请务必提及!
import { AttachFile, InsertEmoticon, Mic, MoreVert } from '@mui/icons-material';
import { Avatar, CircularProgress, IconButton } from '@mui/material';
import InfiniteScroll from 'react-infinite-scroller';
import Head from 'next/head';
import { useState, useEffect } from 'react';
import Message from '../../components/Message.component';
import styles from '../../styles/Chat.module.css'
import { useRouter } from 'next/router'
import {useSelector, useDispatch} from "react-redux"
import {bindActionCreators} from "redux"
import * as chatActions from "../../state/action-creators/chatActions"
const Chat = () => {
const router = useRouter()
const { roomId } = router.query
const auth = useSelector((state)=> state.auth)
const messages = useSelector((state)=> state.chat[roomId].messages)
const dispatch = useDispatch()
const {getMessages, markAsRead, sendMessage} = bindActionCreators(chatActions, dispatch)
const [inputValue, setInputValue] = useState("")
const sendMessageForm = (e) => {
e.preventDefault()
console.log("***inputValue:", inputValue)
sendMessage(roomId, inputValue)
}
const loadMessages = (page) => {
if(roomId)
getMessages(roomId, page)
}
//user-read-message
useEffect(() => {
//user-read-message
markAsRead(roomId, auth.user._id)
}, [messages]);
return (
<div className={styles.container}>
<Head>
<title>Chat</title>
</Head>
<div className={styles.header}>
<Avatar/>
<div className={styles.headerInformation}>
<h3>Zabre el Ayr</h3>
<p>Last Seen ...</p>
</div>
<div className={styles.headerIcons}>
<IconButton>
<AttachFile/>
</IconButton>
<IconButton>
<MoreVert/>
</IconButton>
</div>
</div>
<div className={styles.chatContainer}>
<InfiniteScroll
isReverse={true}
pageStart={0}
loadMore={loadMessages}
hasMore={messages.hasNextPage || false}
loader={<div className={styles.loader} key={0}><CircularProgress /></div>}
>
{Object.keys(messages.docs).map((key, index)=>{
return<Message
key={index}
sentByMe={messages.docs[key].createdBy === auth.user._id}
message={messages.docs[key].msg}
/>})}
</InfiniteScroll>
<span className={styles.chatContainerEnd}></span>
</div>
<form className={styles.inputContainer}>
<InsertEmoticon/>
<input className={styles.chatInput} value={inputValue} onChange={(e)=>setInputValue(e.target.value)}/>
<button hidden disabled={!inputValue} type='submit' onClick={sendMessageForm}></button>
<Mic/>
</form>
</div>)
};
export default Chat;
useSelector
需要一个新对象,其中包含您传递给它的对象的新引用,以便触发 re-render
你用 return {...state}
做的只是为父对象创建一个新对象,而不是 useSelector
正在使用的嵌套对象,在你的情况下是这样的:
const messages = useSelector((state)=> state.chat[roomId].messages)
因此,您应该 return 将整个状态作为一个新对象和一个新的 state.chat[roomId].messages
对象
换句话说,应该更改根对象和正在使用的对象的引用。
我的 NextJS 应用程序发生状态更改后,重新呈现 时遇到问题。
函数 sendMessageForm
启动一个 redux 动作 sendMessage
将消息添加到状态。
问题与减速器中的返回状态无关,因为我正在返回一个新对象(return {...state}
),它应该触发重新渲染!
有什么可能会阻止重新渲染吗?
这是调用和显示状态的文件,所以没有其他文件应该负责!但如果您认为问题可能出在其他地方,请务必提及!
import { AttachFile, InsertEmoticon, Mic, MoreVert } from '@mui/icons-material';
import { Avatar, CircularProgress, IconButton } from '@mui/material';
import InfiniteScroll from 'react-infinite-scroller';
import Head from 'next/head';
import { useState, useEffect } from 'react';
import Message from '../../components/Message.component';
import styles from '../../styles/Chat.module.css'
import { useRouter } from 'next/router'
import {useSelector, useDispatch} from "react-redux"
import {bindActionCreators} from "redux"
import * as chatActions from "../../state/action-creators/chatActions"
const Chat = () => {
const router = useRouter()
const { roomId } = router.query
const auth = useSelector((state)=> state.auth)
const messages = useSelector((state)=> state.chat[roomId].messages)
const dispatch = useDispatch()
const {getMessages, markAsRead, sendMessage} = bindActionCreators(chatActions, dispatch)
const [inputValue, setInputValue] = useState("")
const sendMessageForm = (e) => {
e.preventDefault()
console.log("***inputValue:", inputValue)
sendMessage(roomId, inputValue)
}
const loadMessages = (page) => {
if(roomId)
getMessages(roomId, page)
}
//user-read-message
useEffect(() => {
//user-read-message
markAsRead(roomId, auth.user._id)
}, [messages]);
return (
<div className={styles.container}>
<Head>
<title>Chat</title>
</Head>
<div className={styles.header}>
<Avatar/>
<div className={styles.headerInformation}>
<h3>Zabre el Ayr</h3>
<p>Last Seen ...</p>
</div>
<div className={styles.headerIcons}>
<IconButton>
<AttachFile/>
</IconButton>
<IconButton>
<MoreVert/>
</IconButton>
</div>
</div>
<div className={styles.chatContainer}>
<InfiniteScroll
isReverse={true}
pageStart={0}
loadMore={loadMessages}
hasMore={messages.hasNextPage || false}
loader={<div className={styles.loader} key={0}><CircularProgress /></div>}
>
{Object.keys(messages.docs).map((key, index)=>{
return<Message
key={index}
sentByMe={messages.docs[key].createdBy === auth.user._id}
message={messages.docs[key].msg}
/>})}
</InfiniteScroll>
<span className={styles.chatContainerEnd}></span>
</div>
<form className={styles.inputContainer}>
<InsertEmoticon/>
<input className={styles.chatInput} value={inputValue} onChange={(e)=>setInputValue(e.target.value)}/>
<button hidden disabled={!inputValue} type='submit' onClick={sendMessageForm}></button>
<Mic/>
</form>
</div>)
};
export default Chat;
useSelector
需要一个新对象,其中包含您传递给它的对象的新引用,以便触发 re-render
你用 return {...state}
做的只是为父对象创建一个新对象,而不是 useSelector
正在使用的嵌套对象,在你的情况下是这样的:
const messages = useSelector((state)=> state.chat[roomId].messages)
因此,您应该 return 将整个状态作为一个新对象和一个新的 state.chat[roomId].messages
对象
换句话说,应该更改根对象和正在使用的对象的引用。