简体   繁体   English

当我使用 React 钩子和 React 上下文添加新帖子时,为什么我的 state 会替换我的帖子

[英]Why is my state replacing my posts when I add a new one using React hooks and React context

I'm creating a new app where I want to be able to post updates to my friends.我正在创建一个新应用程序,我希望能够将更新发布给我的朋友。 A micro-blogging site.一个微博网站。

I want to learn how to update the app using React hooks and React's context API.我想学习如何使用 React 钩子和 React 的上下文 API 来更新应用程序。 I created the following provider that takes the state as the value... I want to be able to add a new post and then update the state's posts so that I don't have to fetch the database again (using firestore) I'm really trying to save myself a call to the db...我创建了以下提供程序,它将 state 作为值...我希望能够添加一个新帖子,然后更新该州的帖子,这样我就不必再次获取数据库(使用 firestore)我真的想为自己节省一个对数据库的调用......

Basically, when I call createNewPost within the state, I want to be able to update the current posts section of the state: state.posts but when I update the state after the API call is successful, my entire posts array gets replaced for some reason. Basically, when I call createNewPost within the state, I want to be able to update the current posts section of the state: state.posts but when I update the state after the API call is successful, my entire posts array gets replaced for some reason . Not sure what I might be doing wrong...不知道我可能做错了什么......

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;

If I had to guess I would say you have a stale enclosure of your initial empty posts state within the updateStatePosts function used in your state.如果我不得不猜测,我会说您在 state 中使用的updateStatePosts function 中有一个陈旧的初始空posts state 外壳。 You can use a functional state update to access the previous state to update from.您可以使用功能 state 更新来访问以前的 state 以进行更新。 Functional state updates allow you to update from the previous state, not the state the update was enqueued/enclosed in.功能 state 更新允许您从以前的 state 进行更新,而不是从 state 更新已排队/包含在其中。

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>
}

This function is wrong:这个 function 是错误的:

const updateStatePosts = (payload) => {
        console.log('why is state posts empty?!', state);
        setState({ ...state, posts: [payload, ...state.posts] })
    }

You're using the spread operator correctly for your state, but posts is directly replaced.您为 state 正确使用了扩展运算符,但直接替换了posts You might want to use the following setState :您可能想要使用以下setState

setState({ ...state, posts: [...payload,...state.posts] })

Despite that, you should also refactor your state .尽管如此,您还应该重构您的state Functions are not states so put them outside your state.函数不是状态,所以将它们放在 state 之外。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM