【发布时间】:2021-01-09 18:31:45
【问题描述】:
在我的 Main.js 中,我使用用户名和我关注的用户列表创建了第一个全局状态。
然后,Wall 组件和 FollowSidebar 都会渲染关注列表及其消息(加上主用户的消息)。
到目前为止一切顺利。但是在 FollowSidebar 内一个名为 FollowUser 的嵌套组件中,我有一个 onClick 来删除用户。我的理解是,因为我改变了状态,useEffect 会负责 Wall 组件重新渲染它,但什么也没有发生......我已经在网上检查了几个例子,但到目前为止没有任何帮助我的用例。
不用说我对 React 的经验并不多,而且 Hooks 有点复杂。
这里的代码:
Main.js:
import React, { useEffect, useState } from "react";
import ReactDom from "react-dom";
import db from "./firebase.js";
// Components
import Header from "./components/Header";
import FollowingSidebar from "./components/FollowingSidebar";
import SearchUsers from "./components/SearchUsers";
import NewMessageTextarea from "./components/NewMessageTextarea";
import Wall from "./components/Wall";
// Context
import StateContext from "./StateContext";
function Main() {
const [mainUser] = useState("uid_MainUser");
const [follows, setFollows] = useState([]);
const setInitialFollows = async () => {
let tempFollows = [mainUser];
const user = await db.collection("users").doc(mainUser).get();
user.data().following.forEach(follow => {
tempFollows.push(follow);
});
setFollows(tempFollows);
};
useEffect(() => {
setInitialFollows();
}, []);
const globalValues = {
mainUserId: mainUser,
followingUsers: follows
};
return (
<StateContext.Provider value={globalValues}>
<Header />
<FollowingSidebar />
<SearchUsers />
<NewMessageTextarea />
<Wall />
</StateContext.Provider>
);
}
ReactDom.render(<Main />, document.getElementById("app"));
if (module.hot) {
module.hot.accept();
}
FollowingSidebar 组件:
import React, { useState, useEffect, useContext } from "react";
import db from "../firebase.js";
import StateContext from "../StateContext";
import FollowingUser from "./FollowingUser";
export default function FollowingSidebar() {
const { followingUsers } = useContext(StateContext);
const [users, setUsers] = useState(followingUsers);
useEffect(() => {
const readyToRender = Object.values(followingUsers).length > 0;
if (readyToRender) {
db.collection("users")
.where("uid", "in", followingUsers)
.get()
.then(users => {
setUsers(users.docs.map(user => user.data()));
});
}
}, [followingUsers]);
return (
<section id="following">
<div className="window">
<h1 className="window__title">People you follow</h1>
<div className="window__content">
{users.map((user, index) => (
<FollowingUser avatar={user.avatar} username={user.username} uid={user.uid} key={index} />
))}
</div>
</div>
</section>
);
}
FollowingUser 组件:
import React, { useState, useContext } from "react";
import db from "../firebase.js";
import firebase from "firebase";
import StateContext from "../StateContext";
export default function FollowingUser({ avatar, username, uid }) {
const { mainUserId, followingUsers } = useContext(StateContext);
const [follows, setFollows] = useState(followingUsers);
const removeFollow = e => {
const userElement = e.parentElement;
const userToUnfollow = userElement.getAttribute("data-uid");
db.collection("users")
.doc(mainUserId)
.update({
following: firebase.firestore.FieldValue.arrayRemove(userToUnfollow)
})
.then(() => {
const newFollows = follows.filter(follow => follow !== userToUnfollow);
setFollows(newFollows);
});
userElement.remove();
};
return (
<article data-uid={uid} className="following-user">
<figure className="following-user__avatar">
<img src={avatar} alt="Profile picture" />
</figure>
<h2 className="following-user__username">{username}</h2>
<button>View messages</button>
{uid == mainUserId ? "" : <button onClick={e => removeFollow(e.target)}>Unfollow</button>}
</article>
);
}
墙组件:
import React, { useState, useEffect, useContext } from "react";
import db from "../firebase.js";
import Post from "./Post";
import StateContext from "../StateContext";
export default function Wall() {
const { followingUsers } = useContext(StateContext);
const [posts, setPosts] = useState([]);
useEffect(() => {
console.log(followingUsers);
const readyToRender = Object.values(followingUsers).length > 0;
if (readyToRender) {
db.collection("posts")
.where("user_id", "in", followingUsers)
.orderBy("timestamp", "desc")
.get()
.then(posts => setPosts(posts.docs.map(post => post.data())));
}
}, [followingUsers]);
return (
<section id="wall">
<div className="window">
<h1 className="window__title">Latest messages</h1>
<div className="window__content">
{posts.map((post, index) => (
<Post avatar={post.user_avatar} username={post.username} uid={post.user_id} body={post.body} timestamp={post.timestamp.toDate().toDateString()} key={index} />
))}
</div>
</div>
</section>
);
}
StateContext.js:
import { createContext } from "react";
const StateContext = createContext();
export default StateContext;
【问题讨论】:
-
你是如何实现 StateContext 的?
-
@ImranRafiqRather 我已将其添加到主要消息的末尾。
-
嗯。是的,我检查了..让我再次检查代码:) 我希望所有数据都正确地来自 firestore...
-
是的。我现在看到的是,由于某种原因,FollowingUser 中的 setFollows 实际上并没有更新状态。
-
我创建了一个类似的演示 :) 给我一点时间看看 Mate 发生了什么 :)
标签: javascript reactjs react-hooks use-effect use-state