Running into an issue with my blog search function. When I submit the search form, the filters/params are updated but in order for the requested blog posts to be returned I have to manually refresh the page. Any ideas on how to approach this properly? Also it should be noted that I have an intersection observer in place for infinite scrolling functionality.
export default function Posts (){
const {title} = useParams()
const [searchParams,setSearchParams] = useSearchParams()
const [posts,setPosts] = useState([])
const [morePosts ,setMorePosts] =useState(true)
const [page,setPage ]= useState(0)
const elementRef = useRef(null)
const filter = searchParams.get('filter')
const [searchField,setSearchField] = useState('')
const onSearchChange=(e)=>{
setSearchField(e.target.value)
}
//handle search
const submissionHandler =(e)=>{
e.preventDefault()
e.target.reset()
setSearchParams({filter:searchField})
setSearchField('')
}
const onIntersect=(entries)=>{
if(entries[0].isIntersecting && morePosts ){
fetchPosts(`http://localhost:4000/blog?skip=${page}&limit=1&q=${filter?filter:''}`)
}
}
function fetchPosts(url){
fetch(url,{
method:'get',
mode:'cors',
})
.then(response=>response.json())
.then(data=>{
if (data.posts.length === 0){
setMorePosts(false)
}
else if(data.success){
setPosts(p=>[...p,...data.posts])
setPage(prev=>prev+1)
}
})
}
useEffect(()=>{
const observer = new IntersectionObserver(onIntersect)
if (observer && elementRef.current){
observer.observe(elementRef.current)
}
return ()=>{
if(observer){
observer.disconnect()
}
}
},[posts,filter])
return(
<>
<FormComponent
style={{width:'20rem',alignSelf:'center',marginBottom:'10pt'}}
onSubmit={submissionHandler}
>
<input type='text' placeholder='Search Posts' value={searchField} onChange={e=>onSearchChange(e)}/>
</FormComponent>
{posts.map((post,i)=>{
const publishedDate = new Date(post.published_at)
const options = { year: 'numeric', month: 'short', day: 'numeric' }
const postDate = publishedDate.toLocaleDateString('en-us',options)
return (
<BlogCard
key={i+post.title}
id={i}
cardImage={post.post_img}
slug={post.slug}
title={post.title}
author={post.author}
body={post.body}
date={postDate}
tags={
post.tags.map((tag,i)=>{
return <span
style={{cursor:'pointer'}} key={i} >
{tag}
</span>
})
}
categories={
post.categories.map((cat,i)=>{
return <span
style={{cursor:'pointer'}} key={i} >
{cat}
</span>
})
}
/>
)
})}
{morePosts && <div ref={elementRef}>...Load More Posts</div>}
</>
)
}
When the submissionHandler is run, it failed to empty the "posts" array,along with setting the "morePosts" value to true and "page" value to 0. also it needs to be reset when navigating back to the blog route.
export default function Posts (){
const {title} = useParams()
const [searchParams,setSearchParams] = useSearchParams()
const [posts,setPosts] = useState([])
const [morePosts ,setMorePosts] =useState(true)
const [page,setPage ]= useState(0)
const elementRef = useRef(null)
const filter = searchParams.get('filter')
const [searchField,setSearchField] = useState('')
const location = useLocation()
// create helper function to delete all posts
const resetPostlist =()=>{
setPosts([])
setMorePosts(true)
setPage(0)
}
const onSearchChange=(e)=>{
setSearchField(e.target.value)
}
const submissionHandler =(e)=>{
e.preventDefault()
e.target.reset()
resetPostlist() //placed the reset function here
setSearchParams({filter:searchField})
setSearchField('')
}
//resets to default posts when user navigates to blog
useEffect(()=>{
if (location.pathname === '/blog'){
resetPostlist()
}
},[location])
const onIntersect=(entries)=>{
if(entries[0].isIntersecting && morePosts ){
fetchPosts(`http://localhost:4000/blog?skip=${page}&limit=1&q=${filter?filter:''}`)
}
}
function fetchPosts(url){
fetch(url,{
method:'get',
mode:'cors',
})
.then(response=>response.json())
.then(data=>{
if (data.posts.length === 0){
setMorePosts(false)
}else if (data.success){
setPosts(p=>[...p,...data.posts])
setPage(prev=>prev+1)
}
})
}
useEffect(()=>{
const observer = new IntersectionObserver(onIntersect)
if (observer && elementRef.current){
observer.observe(elementRef.current)
}
return ()=>{
if(observer){
observer.disconnect()
}
}
},[posts,filter])
return(
<>
<FormComponent
style={{width:'20rem',alignSelf:'center',marginBottom:'10pt'}}
onSubmit={submissionHandler}
>
<input type='text' placeholder='Search Posts' value={searchField} onChange={e=>onSearchChange(e)}/>
</FormComponent>
{posts.map((post,i)=>{
const publishedDate = new Date(post.published_at)
const options = { year: 'numeric', month: 'short', day: 'numeric' }
const postDate = publishedDate.toLocaleDateString('en-us',options)
return (
<BlogCard
key={i+post.title}
id={i}
cardImage={post.post_img}
slug={post.slug}
title={post.title}
author={post.author}
body={post.body}
date={postDate}
tags={
post.tags.map((tag,i)=>{
return <span
style={{cursor:'pointer'}} key={i} >
{tag}
</span>
})
}
categories={
post.categories.map((cat,i)=>{
return <span
style={{cursor:'pointer'}} key={i} >
{cat}
</span>
})
}
/>
)
})}
{morePosts && <div ref={elementRef}>...Load More Posts</div>}
</>
)
}