I would like to hide my data if someone is searching my list items. I have imported my searchbar on Homepage and it seems that the data is not rerendering despite I use a conditional variable with useState.
What I am trying to achieve is the fact that at the beggining the user is seeing the search bar with a list of item. Whenever the user is searching for a string, I want to hide my list of items, as the new data will show. Currently whenever the user is searching does retrieve the search items + initial list of items, which is not ok.
Please find my code:
import React, {useState} from 'react'
import { Link } from 'react-router-dom'
import { useQuery, gql } from '@apollo/client'
import SearchReviews from "./SearchReviews"
const REVIEWS = gql`
query GetReviews {
reviews (sort: "createdAt:desc") {
data{
...
}
}
}
}
}
}
`
export default function Homepage() {
const { loading, error, data } = useQuery(REVIEWS)
const [ show, setShow] = useState(true)
if (loading) return <p>Loading...</p>
if (error) return <p>`Error! ${error}`</p>
// console.log(data)
return (
<div>
<SearchReviews onSubmit={e => {
e.preventDefault()
// console.log(e.target[0].value)
setShow(false). <==================HERE
}}/>
{show && (
<div>
{data.reviews.data.map(review => (
<div key={review.id} className="review-card">
<div className="rating">{review.attributes.rating}</div>
<h2>{review.attributes.title}</h2>
<h5>{review.attributes.createdAt.substring(0, 10)}</h5>
{review.attributes.categories.data.map(c => (
<small key={c.id}>{c.attributes.name}</small>
))}
<p>{review.attributes.body.substring(0, 200)}... </p>
<Link to={`/details/${review.id}`}>Read more</Link>
</div>
))}
</div>
)}
</div>
)
}
And with SearchReviews.js
export default function SearchReviews() {
const [ first, setFirst ] = useState(false)
const [ query, setQuery] = useState("")
const { loading, error, data } = useQuery(SEARCH, {skip: !first,variables: {my_query: query}})
if (loading) return <p>Loading data...</p>
if (error) return <p>`Error! ${error}`</p>
// console.log(data)
return (
<div>
<div className="wrap">
<div className="search">
<form onSubmit={e => {
e.preventDefault()
// console.log(e.target[0].value)
setQuery(e.target[0].value)
setFirst(true)
}}>
<input type="search"
placeholder="Search Malware"
className="searchTerm"
id="input_text"
autoComplete="off"
/>
<br/>
{/*<button type="submit" className="searchButton">Submit</button>*/}
</form>
</div>
</div>
{first && (
<div className="dataResult">
{data.reviews.data.map(review => (
<div key={review.id} className="review-card">
<div className="rating">{review.attributes.rating}</div>
<h2>{review.attributes.title}</h2>
<h5>{review.attributes.createdAt.substring(0, 10)}</h5>
{review.attributes.categories.data.map(c => (
<small key={c.id}>{c.attributes.name}</small>
))}
<p>{review.attributes.body.substring(0, 200)}... </p>
<Link to={`/details/${review.id}`}>Read more</Link>
</div>
))}
</div>
)}
</div>
)
}
Currently the old data is not removed despite the form is submitted, which means that the new state is not re-rendered in the DOM, despite the variable is changed. I think I need to return a boolean value from the child component <SearchReviews />
to parent and change the state.
I tried event with something like this:
const updateShow = () => {
setShow(false)
}
return (
<div>
<SearchReviews onChange={updateShow}/>
<Link to={`/search/`}>Search Library</Link>
<button> | </button>
<Link to={`/create`}>Create</Link>
<button> | </button>
<Link to={`/new`}>New</Link>
{show && (
<div>
{data.reviews.data.map(review => (
<div key={review.id} className="review-card">
<div className="rating">{review.attributes.rating}</div>
<h2>{review.attributes.title}</h2>
<h5>{review.attributes.createdAt.substring(0, 10)}</h5>
{review.attributes.categories.data.map(c => (
<small key={c.id}>{c.attributes.name}</small>
))}
<p>{review.attributes.body.substring(0, 200)}... </p>
<Link to={`/details/${review.id}`}>Read more</Link>
</div>
))}
</div>
)}
</div>
)
Any help is much appreciated!
You could pass setShow down to the SearchReviews component as props.
export default function SearchReviews({setShow}) {
const [ first, setFirst ] = useState(false)
const [ query, setQuery] = useState("")
// Call the parent function (passed by props) within the child handler
<form onSubmit={e => {
e.preventDefault()
// console.log(e.target[0].value)
setQuery(e.target[0].value)
setFirst(true)
setShow(false)
}}>
Then in the parent component:
<SearchReviews setShow={setShow}/>