为啥当我使用 React 钩子和 React 上下文添加新帖子时,我的状态会替换我的帖子
Posted
技术标签:
【中文标题】为啥当我使用 React 钩子和 React 上下文添加新帖子时,我的状态会替换我的帖子【英文标题】:Why is my state replacing my posts when I add a new one using React hooks and React context为什么当我使用 React 钩子和 React 上下文添加新帖子时,我的状态会替换我的帖子 【发布时间】:2021-05-07 11:59:06 【问题描述】:我正在创建一个新应用,我希望能够将更新发布给我的朋友。一个微博网站。
我想学习如何使用 React 钩子和 React 的上下文 API 更新应用程序。我创建了以下将状态作为值的提供程序...我希望能够添加一个新帖子,然后更新该州的帖子,这样我就不必再次获取数据库(使用 firestore)我是真的想给自己节省一个对数据库的调用......
基本上,当我在状态中调用 createNewPost 时,我希望能够更新状态的当前帖子部分:state.posts
但是当我在 API 调用成功后更新状态时,我的整个帖子数组被替换因为某些原因。不知道我可能做错了什么......
import createContext, useState from 'react';
import createDoc, getWhere from '../utils/database/db';
export const PostDataContext = createContext();
const SetDataContextProvider = ( children ) =>
const [state, setState] = useState(
posts: [],
timelinePosts: [],
createNewPost: async (collection, payload) =>
const doc = await createDoc(collection, payload)
payload.id = doc?.doc?.id;
updateStatePosts(payload);
return doc;
,
getPostsByUserId: async (userId) =>
const dataReceived = await getWhere('/posts', userId, 'userId')
setState( ...state, posts: dataReceived )
);
const updateStatePosts = (payload) =>
console.log('why is state posts empty?!', state);
setState( ...state, posts: [payload, ...state.posts] )
return <PostDataContext.Provider value=state>
children
</PostDataContext.Provider>
export default SetDataContextProvider;
【问题讨论】:
你是怎么把updateStatePosts
传下来的?
我只是从createNewPost
调用它,但@Drew Reese 帮助我指出了正确的方向......
【参考方案1】:
如果我不得不猜测,我会说您在您的状态中使用的 updateStatePosts
函数中有一个陈旧的初始空 posts
状态外壳。您可以使用功能状态更新来访问要更新的先前状态。功能状态更新允许您从以前的状态进行更新,而不是更新被排队/包含在其中的状态。
const SetDataContextProvider = ( children ) =>
const [state, setState] = useState(
posts: [],
timelinePosts: [],
createNewPost: async (collection, payload) =>
const doc = await createDoc(collection, payload)
payload.id = doc?.doc?.id;
updateStatePosts(payload);
return doc;
,
getPostsByUserId: async (userId) =>
const dataReceived = await getWhere('/posts', userId, 'userId')
setState(prevState => (
...prevState, // <-- preserve any previous state
posts: dataReceived
))
);
const updateStatePosts = (payload) =>
setState(prevState => ( // <-- previous state to this update
...prevState,
posts: [payload, ...prevState.posts],
));
;
return <PostDataContext.Provider value=state>
children
</PostDataContext.Provider>
【讨论】:
【参考方案2】:这个函数是错误的:
const updateStatePosts = (payload) =>
console.log('why is state posts empty?!', state);
setState( ...state, posts: [payload, ...state.posts] )
您正在为您的状态正确使用扩展运算符,但 posts
被直接替换。您可能想使用以下setState
:
setState( ...state, posts: [...payload,...state.posts] )
尽管如此,您还应该重构您的state
。函数不是状态,所以把它们放在你的状态之外。
【讨论】:
谢谢菲利克斯!我认为这部分代码有效,因为我只想在加载时获取数据库一次,问题是当我运行createNewPost
函数时。
ups,使用了错误的功能。更新了它。问题还是一样。以上是关于为啥当我使用 React 钩子和 React 上下文添加新帖子时,我的状态会替换我的帖子的主要内容,如果未能解决你的问题,请参考以下文章
在使用数据库数据更新上下文后,React 'useContext' 钩子不会重新渲染
为啥在 React 中使用 useImperitaveHandle 钩子?