I'm using react with Context Api and react hook form to add a new post. When I submit a post, the new post is in the last position but when I refresh the page, the post goes to the top position. I want the new post to be in the top position immediately. Do you know what I did wrong, please?
PostsContext.tsx
export interface Post {
id: number
content: string
thumbnail: {
url: string
}
created_at: string
updated_at: string
userId: number
}
export interface PostsState {
posts: Post[]
}
export type PostsAction =
| { type: 'SET_POSTS'; payload: Post[] }
| { type: 'ADD_POST'; payload: Post }
const initialState: PostsState = {
posts: [],
}
const reducer = (state: PostsState, action: PostsAction) => {
switch (action.type) {
case 'SET_POSTS':
return { posts: action.payload }
case 'ADD_POST':
return { posts: [...state.posts, action.payload] }
default:
return state
}
}
export const PostsContext = createContext<{
state: PostsState
dispatch: React.Dispatch<PostsAction>
}>({
state: initialState,
dispatch: () => null,
})
export const PostsProvider = ({ children }: PropsWithChildren<{}>) => {
const [state, dispatch] = useReducer(reducer, initialState)
return <PostsContext.Provider value={{ state, dispatch }}>{children}</PostsContext.Provider>
}
Feed.tsx
const Feed = () => {
const { state, dispatch } = usePostsContext()
useEffect(() => {
const fetchPosts = async () => {
const res = await fetch(`${import.meta.env.VITE_API_URL}/api/posts`, {
credentials: 'include',
})
const data = await res.json()
if (res.ok) {
dispatch({ type: 'SET_POSTS', payload: data })
}
}
fetchPosts()
}, [])
return (
<div className="container mx-auto">
<PostForm />
{state.posts.length < 1 ? (
<div className="mt-4 p-8 text-center border border-gray-200 rounded-lg">
<h2 className="text-2xl font-medium">There's nothing here...</h2>
<p className="mt-4 text-sm text-gray-500">
Created posts will appear here, try creating one!
</p>
</div>
) : (
state.posts.map((post) => <Posts key={post.id} post={post} />)
)}
</div>
)
}
export default Feed
PostForm.tsx
const PostForm = () => {
const { dispatch } = usePostsContext()
const {
register,
handleSubmit,
control,
watch,
reset,
formState: { isSubmitSuccessful, errors },
} = useForm<FormInput>({
defaultValues: {
content: '',
},
resolver: yupResolver(postSchema),
})
const selectedFile = watch('thumbnailFile')
const onSubmit: SubmitHandler<FormInput> = async (data) => {
const formData = new FormData()
formData.append('content', data.content)
formData.append('thumbnailFile', data.thumbnailFile[0])
const response = await fetch(`${import.meta.env.VITE_API_URL}/api/posts`, {
method: 'POST',
credentials: 'include',
body: formData,
})
const post = await response.json()
if (response.ok) {
console.log('post created', post)
dispatch({ type: 'ADD_POST', payload: post })
reset()
}
}
return (
<MyForm />
)
}
export default PostForm