[英]How do I prevent this endless re-render in react?
我正在構建一個 React 應用程序,但我還沒有完全了解鈎子的使用。
我的數據以以下格式存儲在 Firestore 中:
userlists > key1 > users: [user1, user2, user3]
> date_created: date
> listname: "Work Colleagues"
> key2 > users: [user1, user4, user5]
> date_created: date
> listname: "Badminton Friends"
(其中 user1、user2 等是保存用戶數據的對象)
所以,在EditUserlistPage
我要檢索的userlist
與主要key1
,並呈現UserList
組件來證明這一點。 UserList
組件然后為每個用戶呈現一個單獨的UserItem
組件
EditUserlistPage
如下( key
通過props傳入):
const EditUserlistPage = (props) => {
// Get list key
const listKey = props.key
// Set up state variables
const [userlist, setUserlist] = useState({})
// Load list from db once component has mounted
useEffect(() => {
props.firebase.getListByKey(listKey).get().then(doc => {
let userlist = doc.data()
setUserList(userList)
})
}, [listKey, props.firebase])
return (
<div>
<h1>Edit User List</h1>
<UserList
userlist={userList}
/>
</div>
)
}
export default withFirebase(EditUserlistPage)
UserList
組件是:
const UserList = (props) => {
// Get list
const { userlist } = props
// Set up state variable - users
const [ users, setUsers] = useState([])
// Now get all users as objects
let usersTemp = []
for(let ii=0; ii<userlist.users.count; ii++) {
const user = userlist.users[ii]
const userItem = {
id: user.index,
name: user.firstname + user.surname
... // More things go here, but I don't think they're relevant
}
usersTemp.push(userItem)
}
}
setUsers(usersTemp)
return (
<div className="userList">
{ // This will render a UserItem component}
</div>
)
}
export default UserList
最后, props.firebase.getListByKey
是:
getListByKey = (key) => this.firestore.collection('userlists').doc(key)
我收到錯誤和警告。
首先,屏幕上顯示的是: Error: Too many re-renders. React limits the number of renders to prevent an infinite loop.
Error: Too many re-renders. React limits the number of renders to prevent an infinite loop.
在控制台中,我也可以看到這個錯誤,它說:
The above error occurred in the <UserList> component:
in UserList (at EditUserlistPage/index.js:59)
in div (at EditUserlistPage/index.js:54)
in EditUserlistPage (at context.js:7)
如果我注釋掉 EditUserlistPage 中呈現 UserList 組件的行,這個錯誤就會消失。
其次,我在控制台中收到警告:
Warning: Can't perform a React state update on an unmounted component. This is a no-op, but it indicates a memory leak in your application. To fix, cancel all subscriptions and asynchronous tasks in a useEffect cleanup function.
in EditUserlistPage (at context.js:7)
context.js 是 Firebase 上下文,並且是:
const FirebaseContext = React.createContext(null)
export const withFirebase = Component => props => (
<FirebaseContext.Consumer>
{firebase => <Component {...props} firebase={firebase} />} // Line 7
</FirebaseContext.Consumer>
)
export default FirebaseContext
我嘗試閱讀有關 Hooks 的 React 文檔,並且我發現如果未正確實現 useEffect 會導致無限重新渲染,但我不知道如何正確執行。
主要問題在於UserList
代碼中的setUsers(usersTemp)
。
每當某些本地狀態發生更改時,組件就會重新渲染。 因此,由於您總是在渲染期間重新設置users
,因此您觸發了另一個渲染。
您可以使用useEffect
並僅在userList
更改時更新users
const UserList = (props) => {
// Get list
const {
userlist
} = props
// Set up state variable - users
const [users, setUsers] = useState([])
useEffect(() => {
// Now get all users as objects
let usersTemp = []
for (let ii = 0; ii < userlist.users.count; ii++) {
const user = userlist.users[ii];
const userItem = {
id: user.index,
name: user.firstname + user.surname
... // More things go here, but I don't think they're relevant
}
usersTemp.push(userItem)
}
}
setUsers(usersTemp)
}, [userlist])
return (
<div className="userList">
{ // This will render a UserItem component}
</div>
)
}
export default UserList
當您使用函數式組件時,當您的狀態更新時,您的整個函數將再次運行。 因此,在您的 UserList 組件中,每次渲染時都會更新狀態,從而觸發新的渲染。
為了防止這種情況,請使用沒有依賴項的 useEffect。 這將導致 useEffect 在組件掛載時只運行一次,非常類似於 componentDidMount。
const UserList = (props) => {
// Get list
const { userlist } = props
// Set up state variable - users
const [ users, setUsers] = useState([])
useEffect(() => {
// Now get all users as objects
let usersTemp = []
for(let ii=0; ii<userlist.users.count; ii++) {
const user = userlist.users[ii]
const userItem = {
id: user.index,
name: user.firstname + user.surname
... // More things go here, but I don't think they're relevant
}
usersTemp.push(userItem)
}
}
setUsers(usersTemp)
},[])
return (
<div className="userList">
{ // This will render a UserItem component}
</div>
)
}
export default UserList
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.