我正在构建一个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
通过道具传递):
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.
在控制台中,我还可以看到此错误,它说:
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)
如果我注释掉呈现UserList组件的EditUserlistPage中的行,此错误就会消失。
第二,我在控制台收到警告:
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可能会导致无限重新渲染(如果实施不正确的话),但是我不知道如何正确地进行渲染。
答案 0 :(得分:2)
主要问题是lapply(subset(airquality, Month == 7), mean, na.rm = T) %>% unlist()
代码中的setUsers(usersTemp)
。
每当更改某些局部状态时,组件都会重新渲染。因此,由于您总是在渲染期间重新设置UserList
,因此会触发另一个渲染。
您可以使用users
并且仅在useEffect
更改时更新users
userList
答案 1 :(得分:1)
使用功能组件时,状态更新时,整个功能将再次运行。因此,在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