在 react-redux 中更改子 reddit(2 次中的 1 次)时,从 reddit API 显示用户头像会崩溃



我已经设法在没有OAuth2的情况下从Reddit API获取用户头像并将其显示在帖子中,但是当更改subreddit时,该应用程序崩溃了1次(2次)。我收到类型错误:无法读取未定义的属性"snoovatar_img"。我认为这与userInfo组件需要来自post组件的postId属性来加载头像的事实有关。如果它没有按时获取 postId,则提取的用户数据是未定义的。由于我在后期组件中渲染了 UserInfo 组件,因此它变成了一个闭合的圆圈。有人知道如何解决它吗?

这是我获取帖子的请求(每次更改subreddit时都会更新):

export const fetchPosts = createAsyncThunk('posts/fetchPosts', async(subreddit) => {
const response = await fetch(`${API_ROOT}${subreddit}.json`)
const dataRow = await response.json()
return dataRow.data.children.map((post) => post.data)
})

以下是我获取用户数据的方式(每次更改subreddit时也会更新):

export const controlFetching = createAsyncThunk('users/fetchUsers', async(subreddit) => {
const response = await fetch(`https://www.reddit.com/${subreddit}.json`)
const posts = await response.json();
const authors = posts.data.children.map((post) => post.data.author)
let allResponse = []
// **it takes each user's name and passes it in the second request to get avatars. The request returns loads of objects with user data so I pushed them all in one array**
for (let i = 0; i <= authors.length-1; i++) {
const userData = await fetch(`${API_ROOT}/user/${authors[i]}/about.json`).then(response1 => response1.json())
allResponse.push( userData.data)}
return allResponse
})

这是 UserInfo 组件,它接受 postId 作为道具来查找与帖子对应的用户并呈现用户头像。

export const UserInfo = ({postId}) => {
const dispatch = useDispatch()
const userStatus = useSelector(state => state.users.userStatus)
const error = useSelector((state) => state.users.userError)
const selectedSubreddit = useSelector(state => state.posts.selectedSubreddit)
const user = useSelector((state) => selectUsersById(state, postId))

useEffect(()=> {

dispatch(controlFetching(selectedSubreddit)) }
, [selectedSubreddit, dispatch]);

let userContent 
if (userStatus === 'loading') {
userContent = <div>Loading...</div>
} else if (userStatus === 'succeeded'){
userContent = 
<img 
src={`${user.snoovatar_img.length !==0 ? user.snoovatar_img : avatar }`}
alt={`${user.snoovatar_img.length !==0 ? user.snoovatar_img : 'avatar' } profile`}
className="avatar-profile-image"  />

} else if (userStatus === 'failed'){
userContent = <div>{error}</div>
}
return (
<section>
{userContent}
</section>
) 
}

这是在其中呈现帖子和头像的帖子列表组件。

let PostContent = ({postId}) => {
const post = useSelector((state) => selectPostById(state, postId))

return (
<article  className="post-content" key={post.id}>
<div className="userInfo">
<UserInfo postId={postId} />

<h5 id='home' className="userName"> by  {post.author}</h5>
</div>
<div className="postContent">
<h3 className="post-title">{post.title}</h3>
<img className="post-image" src={post.url} alt=""/>
</div>
</article>
)
}
export const PostsList = () => {

const dispatch = useDispatch()
const postStatus = useSelector(state => state.posts.status)
const orderedPostIds = useSelector(selectPostIds)
const error = useSelector((state) => state.posts.error)
const selectedSubreddit = useSelector(state => state.posts.selectedSubreddit)
useEffect(()=> {

dispatch(fetchPosts(selectedSubreddit))
}, [selectedSubreddit, dispatch]);
let content 
if (postStatus=== 'loading') {
content = <div>Loading...</div>
} else if(postStatus === 'succeeded'){
content = orderedPostIds.map((postId)=> 
( <PostContent postId = {postId} key={postId}/>
))
} else if(postStatus === 'failed'){
content = <div>{error}</div>
}
return (
<section>
<h2>Posts</h2>
{content}
</section>
) 
}

我也收到这样的警告:不可变状态不变量中间件花了 33 毫秒,这超过了 32 毫秒的警告阈值。将非常感谢任何帮助!

在访问user变量的属性之前,您没有确保该变量存在。 你相信userStatus这样做,但这显然是不可靠的。

改变

else if (userStatus === 'succeeded') {

else if (userStatus === 'succeeded' && user) {

这确保了user变量是真实的。

获取本身只是基于selectedSubreddit,而不是postId,所以如果postId稍后更改,应该没有问题。


我重新设计了您的代码并使其使我们能够通过自己的操作获取每个用户,而不是尝试一次获取所有用户。 我们可以将username作为参数传递。 当这两个组件都包含在后 JSON 中时,UserInfo组件应该依赖于postId而不是username对我来说是没有意义的。

行动

export const fetchUser = createAsyncThunk(
"users/fetchUser",
async (username: string) => {
const response = await fetch(
`https://www.reddit.com/user/${username}/about.json`
);
const json = await response.json();
return json.data;
}
);

元件

export const UserInfo = ({ username }) => {
const dispatch = useDispatch();
const user = useSelector((state) => selectUserByUsername(state, username));
useEffect(() => {
if (!user) {
dispatch(fetchUser(username));
}
}, [username, dispatch, user]);
if (!user) {
return null;
}
return (
<section>
<img
src={`${user.snoovatar_img || user.icon_img}`} // empty string evaluates as false
alt={`user ${username} profile`}
className="avatar-profile-image"
/>
</section>
);
};

PostContent

<UserInfo username={post.author} />

相关内容

  • 没有找到相关文章

最新更新